﻿using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Management;
using System.Net.Http;
using System.Reactive.Subjects;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using DynamicData;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Win32;
using Newtonsoft.Json;
using NPOI.HSSF.UserModel;
using NPOI.OpenXml4Net.OPC;
using NPOI.POIFS.FileSystem;
using NPOI.SS.UserModel;
using NPOI.Util;
using NPOI.XSSF.Extractor;
using OfficeOpenXml;
using Serilog;
using Serilog.Events;
using SimpleTool.ActivityUnit;
using SimpleTool.ActivityUnit.EchoControl;
using SimpleTool.SerialTool.SerialControl;
using SimpleTool.Server;
using SimpleTool.TransformComponent;
using Supabase.Postgrest.Attributes;
using Supabase.Realtime.Models;
using Supabase.Realtime.PostgresChanges;
using static ICSharpCode.SharpZipLib.Zip.ExtendedUnixData;
using static SimpleTool.Server.IDirFileServer;
using static SimpleTool.Server.RuntimeLog;
using static Supabase.Realtime.PostgresChanges.PostgresChangesOptions;

namespace SimpleTool.Server
{
    public class RuntimeLog : IDisposable
    {
        private EnjoyRuntimeLog? MyLog = null;
        private readonly Subject<LogEvent> LogSubscribe = new ();
        private readonly ICollection<object> CacheContents = [];
        private readonly ConcurrentQueue<object> MessageQueue = new ();

        public enum LogType
        {
            Fatal,
            Error,
            Debug,
            Warning,
            Info
        }

        public RuntimeLog()
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel
                .Debug()
                .WriteTo.Observers(subscribe=>subscribe.Subscribe(LogSubscribe))
                .WriteTo.File
            (
                path: LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.RTLog, null, "log"),
                shared: true,
                rollingInterval: RollingInterval.Infinite,
                outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}"
            ).CreateLogger();

            Log.Logger.Debug("logger init  success, exec clear");

            Clear();

            LogSubscribe.Subscribe(logEvent =>
            {
                string sourceContext = logEvent.Properties.TryGetValue("SourceContext", out var value)
                                       ? value.ToString().Trim('"') // 移除多余的引号
                                       : "Unknown";

                string content = $"{DateTime.Now:HH:mm:ss} {sourceContext}: [{logEvent.Level}] {logEvent.RenderMessage()}";

                EnjoyRichTextBox.Text Text = new()
                {
                    Contnet = content,
                    TxType = EnjoyRichTextBox.TextType.Normal
                };

                LogEventLevel Level = logEvent.Level;

                string ForeGround = "DeepMatrix";

                switch (Level)
                {
                    case LogEventLevel.Fatal:

                        ForeGround = "BurgundyNight";

                        break;

                    case LogEventLevel.Error:

                        ForeGround = "CoralRed";

                        break;

                    case LogEventLevel.Warning:

                        ForeGround = "MustardPop";

                        break;

                    case LogEventLevel.Debug:

                        ForeGround = "DeepMatrix";

                        break;

                    case LogEventLevel.Information:

                        ForeGround = "RoyalSignal";

                        break;
                }

                Text.Foreground = ForeGround;

                if (MyLog is null)
                {
                    MessageQueue.Enqueue(Text);
                }
                else
                {
                    MyLog?.Dispatcher.InvokeAsync(() =>
                    {
                        while (!MessageQueue.IsEmpty)
                        {
                            if (MessageQueue.TryDequeue(out object? result))
                            {
                                MyLog?.AddContent(result);
                            }
                        }
                        MyLog?.AddContent(Text);
                    }, DispatcherPriority.Background);
                }
            });
        }

        public bool IsOpenlogFace()
        {
            return MyLog is not null and Window _Window && _Window.Visibility == Visibility.Visible;
        }

        private static async void Clear()
        {
            DirFileServer dirfileServer = new ();

            await dirfileServer.GetLocalFilesAsync(new LocalFileFilterOptions(
                LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.RTLogDir), string.Empty, string.Empty, (file) =>
            {
                if (!string.IsNullOrEmpty(file.Item1))
                {
                    foreach (var match in dirfileServer.GetSimpleName(file.Item1).MatchTime(5))
                    {
                        if (DateTime.TryParseExact(match, match.ConvertDateFormat(), CultureInfo.InvariantCulture,
                            DateTimeStyles.None, out DateTime _time))
                        {
                            if ((DateTime.Now.Month == _time.Month && DateTime.Now.Day - _time.Day > 10) ||
                                DateTime.Now.Month != _time.Month)
                            {
                                File.Delete(file.Item1); //  clear cache
                            }
                        }
                    }
                }
            }, LocalFileFilterOptions.Mode.Exact));

            dirfileServer.Dispose();

            Log.Logger.Print(RuntimeLog.LogType.Debug, "logger exec clear success");
        }

        public void OpenConsolute(bool Cut)
        {
            Application.Current.Dispatcher.InvokeAsync(async () =>
            {
                if (Cut)
                {
                    while (Application.Current.MainWindow.Visibility != Visibility.Visible)
                    {
                        await Task.Delay(100);
                    }
                    MyLog = new();
                    MyLog.Showy();
                    MyLog.ClosedCallBack = (objects) =>
                    {
                        CacheContents.Reteller(objects, true);
                        MyLog = null;
                    };
                }
                else
                {
                    MyLog?.Dispose();
                }
            });
        }

        public void Dispose()
        {
            MyLog?.Dispatcher.Invoke(async () =>
            {
                Log.Logger.Print(LogType.Warning, "release realtime log");
                MyLog?.Close();
                MyLog = null;
                LogSubscribe.Dispose();
                await Log.CloseAndFlushAsync();
            });

            GC.SuppressFinalize(this);
        }
    }

    public class PowerPlantServer : IPowerPlantServer, IDisposable
    {
        public PowerPlantServer()
        {
            EventAddWatcher.EventArrived += InvokeAddCallBack;
            EventDelWatcher.EventArrived += InvokeDelCallBack;
        }

        private readonly ManagementEventWatcher EventAddWatcher = new (new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType=2"));

        private readonly ManagementEventWatcher EventDelWatcher = new (new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType=3"));

        private Action<bool>? MoniterCallBack;

        public delegate void ReceiveBuffContent(string conent);

        private readonly SerialPort SerialEngine = new();

        private readonly ILogger Logger = Log.Logger.ForContext<PowerPlantServer>();

        private ReceiveBuffContent? ReceiveAction;

        private readonly Function Function = new ();

        private bool _disposed = false;

        private int SubcriptCount = 0;

        public string Name()
        {
            return SerialEngine.PortName;
        }

        public void Instance(Action<SerialPort> ObjectCallBack)
        {
            ObjectCallBack.Invoke(SerialEngine);
        }

        private void InvokeAddCallBack(object sender, EventArrivedEventArgs e)
        {
            MoniterCallBack?.Invoke(true);
        }

        private void InvokeDelCallBack(object sender, EventArrivedEventArgs e)
        {
            //  重新插拔串口可能回导致事件被多次订阅，实际表现为多次输出串口内容
            for (int count = 0; count < SubcriptCount; count++)
            {
                SerialEngine.DataReceived -= ReceiveSerialOutPut;
                SubcriptCount--;
            }
            MoniterCallBack?.Invoke(false);
        }

        public void Moniter(Action<bool>? ChangeSeek, int ActionType = 1, bool isOpen = false)
        {
            if (ChangeSeek != null) MoniterCallBack = ChangeSeek;

            switch (ActionType)
            {
                case 0:
                    if (isOpen) 
                    {
                        EventDelWatcher.Start();
                    }
                    else
                    {
                        EventDelWatcher.Stop();
                    }
                    break;

                case 1:
                    if (isOpen)
                    {
                        EventAddWatcher.Start();
                    }
                    else
                    {
                        EventAddWatcher.Stop();
                    }
                    break;
            }
        }

        public bool Execute(string command)
		{
            if (SerialEngine.IsOpen)
            {
                try
                {
                    string commandTrim = RegExp.RegExpWrapWork().Replace(command, string.Empty);

                    SerialEngine.Write(commandTrim + "\r\n");

                    Logger.Print(RuntimeLog.LogType.Info, $"serial cmd write: {commandTrim.Replace("\r", "\\r").Replace("\n", "\\n")}  where port name {SerialEngine.PortName}");
                }
                catch (Exception error)
                {
                    Logger.Print(RuntimeLog.LogType.Debug, $"seral order execute error: {error.Message}");
                }
                return true;
            }
            else
            {
                return false;
            }
		}

		public async void Write(ICollection<CommandSectionModel.CommandStruct> pushs)
        {
            if (SerialEngine.IsOpen)
            {
                foreach (var commandinfos in pushs)
                {
                    string command = commandinfos.Command;
                    await Task.Delay(commandinfos.Duration);
                    Execute(command);
                }
            }
        }

        public (bool, string) Action(int stat = 1)
        {
            bool returnFlag = false;
            try
            {
                switch (stat)
                {
                    case 0:
                        if (SerialEngine.IsOpen)
                        {
                            SerialEngine.Close();
                            if (!SerialEngine.IsOpen)
                            {
                                returnFlag = true;
                                Subscribe(false);
                            }
                        }
                        break;

                    case 1:
                        if (SerialEngine.IsOpen) SerialEngine.Close();
                        SerialEngine.Open();
                        if (SerialEngine.IsOpen)
                        {
                            returnFlag = true;
                            Subscribe();
                        }
                        break;

                    case 2:
                        returnFlag = SerialEngine.IsOpen;
                        break;
                }
            }catch (Exception error)
            {
                Logger.Error($"{this} action error: {error.Message}");
                return (false, error.Message);
            }
            return (returnFlag, string.Empty);
		}
		
        public void Subscribe(bool isSubscribe = true)
		{
            if (isSubscribe)
            {
                SerialEngine.DataReceived += ReceiveSerialOutPut;
                SubcriptCount++;
                Logger.Print(LogType.Debug, $"start subscript where port name {SerialEngine.PortName} subcript count {SubcriptCount}");
            }
            else
            {
                SubcriptCount--;
                SerialEngine.DataReceived -= ReceiveSerialOutPut;
                Logger.Print(LogType.Debug, $"cancel subscript where port name {SerialEngine.PortName} subcript count {SubcriptCount}");
            }
        }

		public void Read<T>(ReceiveBuffContent action)
        {
            ReceiveAction = action;
            Logger.Debug($"serial output object change: {typeof(T).Name}");
        }

        private void ReceiveSerialOutPut(object sender, SerialDataReceivedEventArgs e)
        {
            string readContent = SerialEngine.ReadExisting();

            Function.FragmentProcessingFactory(readContent, (IntactContent)=>
            {
                ReceiveAction?.Invoke(IntactContent);
            });
        }

        public void BuffClear()
        {
            SerialEngine.DiscardInBuffer();
            SerialEngine.DiscardOutBuffer();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            lock (this)
            {
                try
                {
                    if (!_disposed)
                    {
                        if (disposing)
                        {
                            Subscribe(false);
                            EventAddWatcher.EventArrived -= InvokeAddCallBack;
                            EventDelWatcher.EventArrived -= InvokeDelCallBack;
                            Action(0);
                            SerialEngine.Dispose();
                        }
                        _disposed = true;
                    }
                }
                catch (Exception error)
                {
                    Logger.Debug($"{this} -> release, where lock stat {error.Message}");
                }
            }
        }

        ~PowerPlantServer()
        {
            Dispose(false);
        }
    }

    public class SerialConfigServer : ISerialServer
    {
        public ObservableCollection<string> ReceiveSerialInfo(EmSerialInfoType type)
        {
            ObservableCollection<string> SerialAttributes = [];
            switch (type) {

                case EmSerialInfoType.BundRate:
                    int[] commonBaudRates =
                    [
                        300,
                        600,
                        1200,
                        2400,
                        4800,
                        9600,
                        14400,
                        19200,
                        38400,
                        57600,
                        115200,
                        128000,
                        256000,
                        500000,
                        921600,
                        1000000,
                        2000000
                    ];
                    foreach (int baud in commonBaudRates)
                    {
                        string c_baud = baud.ToString();
                        SerialAttributes.Add(c_baud);
                        ConfigSectionModel.SerialConfigInfoMap.Com.SerialComBaudMap.TryAdd(c_baud, baud);
                    }
                    break;

                case EmSerialInfoType.StopBits:
                    foreach (StopBits stop in Enum.GetValues(typeof(StopBits)))
                    {
                        if (stop != StopBits.None)
                        {
                            string c_stop = stop.ToString();
                            SerialAttributes.Add(c_stop);
                            ConfigSectionModel.SerialConfigInfoMap.Com.SerialComStopMap.TryAdd(c_stop, stop);
                        }
                    }
                    break;

                case EmSerialInfoType.Databits:

                    int[] numbers = [5, 6, 7, 8];

                    foreach (int data in numbers) 
                    {
                        string c_data = data.ToString();
                        SerialAttributes.Add(c_data);
                        ConfigSectionModel.SerialConfigInfoMap.Com.SerialComDataMap.TryAdd(c_data, data);
                    }
                    break;

                case EmSerialInfoType.ParityBits:
                    foreach (Parity parity in Enum.GetValues(typeof(Parity)))
                    {
                        string c_parity = parity.ToString();
                        SerialAttributes.Add(c_parity);
                        ConfigSectionModel.SerialConfigInfoMap.Com.SerialComParityMap.TryAdd(c_parity, parity);
                    }
                    break;

                case EmSerialInfoType.HandShakes:
                    foreach (Handshake hand in Enum.GetValues(typeof(Handshake)))
                    {
                        string c_hand = hand.ToString();
                        SerialAttributes.Add(c_hand);
                        ConfigSectionModel.SerialConfigInfoMap.Com.SerialComHandShakeMap.TryAdd(c_hand, hand);
                    }
                    break;
            }
            return SerialAttributes;
        }
    }

    public class DatabaseServer(IDirFileServer _dirfileSeriver,
                                IDenCryptoGraphicServer _dencryptServer) : IDataBaseServer, IDisposable
    {
        class UserPresence : BasePresence
        {
            [JsonProperty("cursorX")]
            public bool IsTyping { get; set; }
            [JsonProperty("onlineAt")]
            public DateTime OnlineAt { get; set; }
        }

        private readonly ILogger Logger = Log.Logger.ForContext<DatabaseServer>();

        private readonly IDirFileServer dirfileSeriver = _dirfileSeriver;

        private readonly IDenCryptoGraphicServer dencryptServer = _dencryptServer;

        private readonly Dictionary<string, SqliteConnection> DBLocalManager = [];

        private readonly Dictionary<string, Supabase.Client> DBCloudManager = [];

        private string SupabaseAddreass = "https://hvoildbpqjyqvfptcjzz.supabase.co";

        private string SupabasePassWord = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imh2b2lsZGJwcWp5cXZmcHRjanp6Iiwicm9sZSI6ImFub24iLCJpYXQiO" +
                                          "jE3NDc3OTU3MDIsImV4cCI6MjA2MzM3MTcwMn0.-jqZO95mNPrBfqWcbIti7pjRTohvfDp6j1a_0HK8FuU";

        private string LocalDBpath = Directory.GetCurrentDirectory();

        private string LocalDBkey = "Auto";

        private string DBKey = string.Empty;

        private DB.DB_TYPE DBtypeIdentify = DB.DB_TYPE.DB_Null;

        private readonly ICollection<Supabase.Realtime.RealtimeChannel> RealtimeChannels = [];

        private readonly string safetyKey = "Njb0317194%&*";

        private readonly SemaphoreSlim _asyncLock = new (1, 1);

        public Action<string, string>? RealtimeChannel = (name, type) => { };

        private readonly Dictionary<string, int> ChannelCountMap = [];

        public bool AlterLocalDBkey(string key)
        {
            if (DBLocalManager != null)
            {
                if (DBLocalManager.ContainsKey(key))
                {
                    DBKey = key;
                    return true;
                }
            }
            return false;
        }

        public KeyValuePair<string, string> GetImportantInfo(bool cloud = true)
        {
            if (cloud)
            {
                return new KeyValuePair<string, string>(SupabaseAddreass, SupabasePassWord);
            }
            else
            {
                return new KeyValuePair<string, string>(LocalDBpath, LocalDBkey);
            }
        }

        public void SetImportantInfo(KeyValuePair<string, string> info, bool cloud = true)
        {
            if (cloud)
            {
                SupabaseAddreass = info.Key;
                SupabasePassWord = info.Value;
            }
            else
            {
                LocalDBpath = info.Key;
                LocalDBkey = info.Value;
            }
        }

        //  访问当前数据库类型
        public DB.DB_TYPE GetDBIdentify()
        {
            return DBtypeIdentify;
        }

        private static string PathBodyName(string key)
        {
            string expectkey = string.Empty;
            ICollection<string> splitkey = [.. key.Split('.')];
            if (0 < splitkey.Count)
            {
                expectkey = splitkey.First();
            }
            return expectkey;
        }

        //  早期数据库初始化，以该方法的回调为准，数据库初始化之后，对于需要返回值的方法，可以使用GetDBIdentify访问当前数据库类型，不要求返回数据的方法
        //  则可以继续使用当前方法
        public async Task<DB.DB_TYPE> CheckDBSurvival(string? dbkey = null)
        {
            TaskCompletionSource Token = new();

            DB.DB_TYPE DBType = DB.DB_TYPE.DB_Null;

            if (DBtypeIdentify == DB.DB_TYPE.DB_Null)
            {
                Stopwatch TimeoutWatch = Stopwatch.StartNew();
                DispatcherTimer? DBconnectTimer = null;
                DBconnectTimer = new DispatcherTimer(
                                    TimeSpan.FromMilliseconds(500),
                                    DispatcherPriority.Normal, //  改为 DispatcherPriority.SystemIdle
                                    (s, e) =>
                                    {
                                        if (DBCloudManager.ContainsKey(DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)))
                                        {
                                            DBconnectTimer?.Stop();
                                            DBconnectTimer = null;
                                            DBType = DB.DB_TYPE.DB_Cloud;
                                            Token.SetResult();
                                        }

                                        if (DBLocalManager.Count > 0 && dbkey != null)
                                        {
                                            foreach (var dict in DBLocalManager)
                                            {
                                                if (PathBodyName(dict.Key) == PathBodyName(dbkey) &&
                                                    dict.Value.State == System.Data.ConnectionState.Open)
                                                {
                                                    DBconnectTimer?.Stop();
                                                    DBconnectTimer = null;
                                                    DBType = DB.DB_TYPE.DB_Local;
                                                    break;
                                                }
                                            }
                                        }

                                        if (TimeoutWatch.ElapsedMilliseconds > 5000)
                                        {
                                            DBconnectTimer?.Stop();
                                            DBconnectTimer = null;
                                            Token.SetResult();
                                        }
                                    },
                                    Application.Current.Dispatcher);
            }
            
            else
            {
                DBType = DBtypeIdentify;
                Token.SetResult();
            }
            
            await Token.Task;

            return DBType;
        }

        public async Task<SqliteExceuteResult> LocalDBQuery(ICollection<string> sqls)
        {
            SqliteExceuteResult exceuteResult = new ();
            try
            {
                Dictionary<string, Dictionary<string, ICollection<object>>> TotalResult = [];
                if (DBLocalManager.TryGetValue(DBKey, out SqliteConnection? connect))
                {
                    if (connect.State == System.Data.ConnectionState.Open)
                    {
                        foreach (var sql in sqls)
                        {
                            await _asyncLock.WaitAsync();
                            using var transation = connect.BeginTransaction(deferred: true);
                            try
                            {
                                string privious = RegExp.RegExpBlank().Split(sql.Trim()).GetSafetyChar(0).Trim();
                                var command = connect.CreateCommand();
                                command.Transaction = transation;
                                command.CommandText = sql;

                                if (privious.Contains("select", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    string CentraContent = RegExp.RegExpSqlCountFormat().Match(sql).Groups[1].Value;

                                    if (!CentraContent.Contains("COUNT(*)", StringComparison.CurrentCultureIgnoreCase))
                                    {
                                        using SqliteDataReader reader = await command.ExecuteReaderAsync();
                                        ICollection<string> columnNames = [.. Enumerable.Range(0, reader.FieldCount).Select(reader.GetName)];
                                        Dictionary<string, ICollection<object>> secResult = [];
                                        while (reader.Read())
                                        {
                                            foreach (string field in columnNames)
                                            {
                                                if (secResult.TryGetValue(field, out ICollection<object>? value))
                                                {
                                                    value.Add(reader[field]);
                                                    secResult[field] = value;
                                                }
                                                else
                                                {
                                                    secResult.TryAdd(field, [reader[field]]);
                                                }
                                            }
                                        }
                                        if (secResult.Count > 0) TotalResult.TryAdd(sql, secResult);
                                    }
                                    else
                                    {
                                        object? Count = await command.ExecuteScalarAsync();

                                        if (Count is not null && long.TryParse(Count.GetSafetyChar(), out long _Count))
                                        {
                                            exceuteResult.ScalarNumber = _Count;
                                        }
                                    }
                                }
                                else if (privious.Contains("update", StringComparison.InvariantCultureIgnoreCase) ||
                                         privious.Contains("insert", StringComparison.InvariantCultureIgnoreCase) ||
                                         privious.Contains("delete", StringComparison.InvariantCultureIgnoreCase) ||
                                         privious.Contains("create", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    exceuteResult.ChangeRow = await command.ExecuteNonQueryAsync();
                                }
                                transation.Commit(); //  out of loop, because it release the transation
                            }
                            catch (Exception error)
                            {
                                transation.Rollback();
                                Logger.Error($"sql action error: {error.Message} {sql}");
                                exceuteResult.ErrorHint = error.Message;
                            }
                            finally
                            {
                                _asyncLock.Release();
                            }
                        }
                    }
                    else
                    {
                        Logger.Warning("local db is not open");
                    }

                    exceuteResult.Result = TotalResult;
                }
                else
                {
                    Logger.Error("database is not open");
                    exceuteResult.ErrorHint = "Fail";
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
                exceuteResult.ErrorHint = error.Message;
            }
            return exceuteResult;
        }

        /// <summary>
        /// main key-> sql;
        /// secondary key-> table field;
        /// secondary values-> table values collection;
        /// </summary>
        /// <param name="sqls"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public async Task<SqliteExceuteResult> LocalDBQueryFree(params string[] sqls)
        {
            SqliteExceuteResult exceuteResult = await LocalDBQuery([.. sqls]);
            return exceuteResult;
        }

        /// <summary>
        /// default dir-> exec diretory;
        /// default name-> database;
        /// default password-> none;
        /// </summary>
        /// <param name="path"></param>
        /// <param name="name"></param>
        /// <param name="password"></param>
        /// <param name="way"></param>
        /// <exception cref="ArgumentException"></exception>
        public void InitLocalDB(SqliteConnectionConfig Configurate, Action<bool>? InitNotify)
        {
            Stopwatch DBTimeCount = Stopwatch.StartNew();

            _= Task.Run(async () =>
            {
                try
                {
                    ICollection<string> connectPatams = [];
                    string SourcePath = "DataSource=" + System.IO.Path.Combine(Configurate.Path, $"{Configurate.Name}.db");
                        
                    connectPatams.Add(SourcePath); 
                    DBKey = dirfileSeriver.GetSimpleName(SourcePath);

                    if (DBLocalManager.TryGetValue(DBKey, out SqliteConnection? connection) &&
                        connection.State == System.Data.ConnectionState.Open)
                    {
                        InitNotify?.Invoke(true);
                    }
                    else
                    {
                        string verityPassword = dirfileSeriver.RegistryAction(1, Registry.CurrentUser, "UpperSimpleTool", "DBCache", DBKey);
                        string FirstIdeaDBKey = 5.GetDesorderly();
                        string ExistsIdeaDBKey = string.Empty;
                        if (string.IsNullOrEmpty(verityPassword))
                        {
                            //  无缓存密钥时创建密钥，并缓存
                            string encryptKey = await dencryptServer.EnCryptoGraphic(FirstIdeaDBKey, safetyKey);
                            connectPatams.Add("Password" + "=" + FirstIdeaDBKey);
                            Logger.Information("send start registry key: " + FirstIdeaDBKey);
                            dirfileSeriver.RegistryAction(0, Registry.CurrentUser, "UpperSimpleTool", "DBCache", DBKey, encryptKey);
                        }
                        else
                        {
                            //  存在参数指定的密钥时，应用它
                            if (!string.IsNullOrEmpty(Configurate.Password))
                            {
                                ExistsIdeaDBKey = Configurate.Password;
                            }
                            else
                            {
                                //  使用缓存的密钥，并解码它
                                ExistsIdeaDBKey = await dencryptServer.DeCryptoGraphic(verityPassword, safetyKey);
                            }
                            connectPatams.Add("Password" + "=" + ExistsIdeaDBKey);
                            Logger.Print(RuntimeLog.LogType.Info, "decrypt registry key: " + ExistsIdeaDBKey, DBTimeCount.ElapsedMilliseconds);
                        }
                        connectPatams.Add("Mode" + "=" + $"{Configurate.Way}");
                        try
                        {
                            SqliteConnection connect = new(string.Join(";", connectPatams));
                            connect.Open(); //  打开数据库之后才能设置密钥，当首次密钥生成时才设置，后续将走使用指定密钥或缓存密钥流程，不在运行以下密钥设置代码
                            if (connect.State == System.Data.ConnectionState.Open)
                            {
                                DBtypeIdentify = DB.DB_TYPE.DB_Local;
                                DBLocalManager.TryAdd(DBKey, connect);
                                DBLocalManager[DBKey].DefaultTimeout = 7;
                                InitNotify?.Invoke(true);
                                if (!string.IsNullOrEmpty(verityPassword))
                                {
                                    _ = LocalDBQueryFree(
                                        $"PRAGMA key = '{ExistsIdeaDBKey}'" +
                                        "PRAGMA cipher_compatibility = 4;" +
                                        "PRAGMA kdf_iter = 2560;" +
                                        "PRAGMA cipher_use_hmac = ON;" +
                                        "PRAGMA cipher_page_size = 4096;" +
                                        "PRAGMA busy_timeout = 2000;"
                                        );
                                    //  cipher_compatibility SQLCipher 3 兼容性
                                    //  kdf_iter 设置密钥派生函数的迭代次数
                                    //  cipher_use_hmac 启用HMAC校验
                                    //  cipher_page_size 设置加密页面大小
                                }
                                Logger.Print(RuntimeLog.LogType.Debug, $"db is connect, where dbkey: {DBKey}", DBTimeCount.ElapsedMilliseconds);
                            }
                            else
                            {
                                InitNotify?.Invoke(false);
                                Logger.Print(RuntimeLog.LogType.Debug, $"db open fail, where dbkey: {DBKey}");
                            }
                        }
                        catch (Exception error)
                        {
                            InitNotify?.Invoke(false);
                            Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} {error.Message}");
                        }
                    }
                }
                catch (Exception error)
                {
                    Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
                }
            }).ConfigureAwait(false);
        }

        public async void InitCloudDB(string address, string key, Action<bool>? InitNotify)
        {
            async void CloudAnchorChannel()
            {
                int maxRetry = 3; //  监听遭遇错误时的重试次数
                                  //  处理监听返回数据
                void response(string name, PostgresChangesResponse e)
                {
                    PostgresChangesPayload<Supabase.Realtime.Socket.SocketResponsePayload>? Payload = e.Payload;
                    Logger.Print(LogType.Warning, 777, name, Payload is null);
                    if (Payload is not null)
                    {
                        Supabase.Realtime.Socket.SocketResponsePayload<Supabase.Realtime.Socket.SocketResponsePayload>? response = Payload.Data;
                        Logger.Print(LogType.Warning, 777, response is not null , response.Table is not null , response._type is not null);
                        if (response is not null && response.Table is not null && response._type is not null)
                        {
                            RealtimeChannel?.Invoke(name, response._type);
                        }
                    }
                }

                while (maxRetry > 0)
                {
                    try
                    {
                        //  所有表监听，并添加监听句柄至字典
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<ProductConfigField>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(ProductConfigField), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<ProductConfigRelation>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(ProductConfigRelation), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<WorkOrderUnfold>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(WorkOrderUnfold), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<WorkOrderPreview>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(WorkOrderPreview), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<DbFieldRelation>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(DbFieldRelation), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<SerialConfig>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(SerialConfig), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<SerialCommand>().On(ListenType.All, (sender, change) =>
                        {
                            response(nameof(SerialCommand), change);
                        }));
                        RealtimeChannels.Add(await DBCloudManager[DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache)]
                            .From<TestResultRegister>().On(ListenType.All, (sender, change) =>
                            {
                                response(nameof(TestResultRegister), change);
                            }));
                        Logger.Print(RuntimeLog.LogType.Info, $"CloudAnchorChannel realtime init success");
                        break;
                    }
                    catch (Exception error)
                    {
                        Logger.Print(RuntimeLog.LogType.Warning, $"CloudAnchorChannel {error.Message}");
                    }
                    maxRetry--;
                }
            }

            try
            {
                if (DBCloudManager.TryGetValue(DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache), out Supabase.Client? _Client))
                {
                    InitNotify?.Invoke(true);
                }
                else 
                {
                    Supabase.SupabaseOptions options = new()
                    {
                        AutoConnectRealtime = true,
                    };
                    var supabase = new Supabase.Client(address, key, options);

                    int maxTimeoutNum = 4;
                    bool initializeState = false;

                    while (maxTimeoutNum > 0)
                    {
                        var isconnect = await supabase.InitializeAsync();
                        if (isconnect is not null)
                        {
                            DBtypeIdentify = DB.DB_TYPE.DB_Cloud;
                            DBCloudManager.TryAdd(DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache), supabase);
                            InitNotify?.Invoke(true);

                            CloudAnchorChannel();

                            initializeState = true;

                            Logger.Print(LogType.Info, "cloud init success, break task now");

                            break;
                        }
                        maxTimeoutNum--;
                    }

                    if (!initializeState)
                    {
                        InitNotify?.Invoke(false);
                    } 
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"InitCloudDB Error: {error.Message}");
                InitNotify?.Invoke(false);
            }
        }

        public async Task CloudAnchorChannel<Table>(Action feedback, Action start, Action? uncork = null, string? type = null, int maxAbnormalCount = 3)
        {
            TaskCompletionSource Token = new ();
            string table = typeof(Table).Name;
            bool WatchState = false;
            DispatcherTimer? Timer = null;

            try
            {
                RealtimeChannel = (_table, _type) =>
                {
                    Logger.Print(RuntimeLog.LogType.Warning, $"table {table} -> {_type} action success3333");
                    if (table == _table && !WatchState)
                    {
                        Logger.Print(RuntimeLog.LogType.Warning, $"table {table} -> {_type} action success");

                        if ((type is not null && _type == type) || type == null)
                        {

                            WatchState = true;
                            feedback.Invoke();
                            if (!Token.Task.IsCompleted) Token.SetResult();
                        }
                    }
                };

                start.Invoke();

                await Task.Delay(3000);

                Timer = new DispatcherTimer(TimeSpan.FromMilliseconds(3000), DispatcherPriority.Normal, (a, e) =>
                {
                    if (!WatchState)
                    {
                        ref int _count = ref CollectionsMarshal.GetValueRefOrAddDefault(ChannelCountMap, table, out bool exists);
                        if (_count < maxAbnormalCount)
                        {
                            _count++;
                        }
                        else
                        {
                            ChannelCountMap.Remove(table);
                            Timer?.Stop();
                            uncork?.Invoke();
                            if (!Token.Task.IsCompleted) Token.SetResult();
                        }
                        start.Invoke();
                    }
                    else
                    {
                        Timer?.Stop();
                        if (!Token.Task.IsCompleted) Token.SetResult();
                    }
                }, Application.Current.Dispatcher);

                await Token.Task;
            } 
            catch (Exception error)
            {
                Logger.Print(LogType.Error, $"CloudAnchorChannel {error.Message}");
            }
        }

        public Supabase.Client? GetCloudDB()
        {
            if (DBCloudManager.TryGetValue(DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache), out Supabase.Client? connection))
            {
                return connection;
            }
            return null;
        }

        public void TemporaryRelease(bool isCloud = true)
        {
            if (isCloud)
            {
                if (DBLocalManager.TryGetValue(DBKey, out SqliteConnection? connection))
                {
                    connection?.Close();
                    connection?.Dispose();
                    DBLocalManager.Clear();
                }
            }
            else
            {
                if (DBCloudManager.TryGetValue(DB.G_MapKeyName(DB.DB_MAPKEY.CloudDataCache), out Supabase.Client? connection))
                {
                    foreach(var i in RealtimeChannels)
                    {
                        i.Unsubscribe();
                    }
                    connection.Realtime.Disconnect();
                    DBCloudManager.Clear();
                }
            }
        }

        private readonly object _syncobj = new();

        public bool _disposed = false;

        /// <summary>
        /// release occupy source
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            bool _synclock = false;

            try
            {
                if (!_disposed)
                {
                    Monitor.Enter(_syncobj, ref _synclock);
                    if (DBLocalManager != null && disposing && _synclock)
                    {
                        foreach (var key in DBLocalManager.Keys)
                        {
                            DBLocalManager[key].Close();
                            DBLocalManager[key].Dispose();
                        }
                        DBLocalManager.Clear();
                    }
                    _disposed = true;
                }
            }
            finally
            {
                if (_synclock) Monitor.Exit(_syncobj);
                Logger.Debug($"{this} -> release, where lock stat {_synclock}");
            }
        }

        public async Task<bool> CheckField<FiedType>(string table, string field, FiedType value)
        {
            await _asyncLock.WaitAsync();
            bool check = false;
            if (DBLocalManager.TryGetValue(DBKey, out SqliteConnection? connect))
            {
                using var transation = connect.BeginTransaction(deferred: true);
                try
                {
                    var command = connect.CreateCommand();
                    command.Transaction = transation;
                    command.CommandText = $"SELECT {field} FROM {table}";
                    using SqliteDataReader reader = command.ExecuteReader();
                    ICollection<object> collection = [];
                    while (reader.Read())
                    {
                        collection.Add(reader[field]);
                    }
                    transation.Commit();
                    if (value is not null && collection.Contains(value))
                    {
                        check = true;
                    }
                    else check = false;
                }
                catch
                {
                    check = false;
                }
            }
            else check = false;
            _asyncLock.Release();

            return check;
        }

        ~DatabaseServer()
        {
            Dispose(false);
        }

    }

    public class DirFileServer : IDirFileServer, IDisposable
    {
        private readonly ILogger Logger = Serilog.Log.Logger.ForContext<DirFileServer>();

        private CancellationTokenSource TokenSource;

        public DirFileServer()
        {
            TokenSource = new();
        }

        public Encoding EncodingSee(string file)
        {
            using StreamReader streamReader = new (path: file, detectEncodingFromByteOrderMarks: true);
            streamReader.Peek();
            return streamReader.CurrentEncoding;
        }

        public async Task<string?> ReadAsync(string file, Encoding? encoding = null)
        {
            try
            {
                using FileStream fstream = new(file, FileMode.Open, FileAccess.Read);
                using StreamReader rstream = new(stream: fstream, encoding ?? EncodingSee(file));
                return await rstream.ReadToEndAsync();
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Debug, $"{ReadAsync} Error: {error.Message}");
            }
            return null;
        }

        public StreamReader? ReadStreamAsync(string file, Encoding? encoding = null)
        {
            StreamReader? rstream = null;
            try
            {
                using FileStream fstream = new(file, FileMode.Open, FileAccess.Read);
                rstream = new(stream: fstream, encoding ?? EncodingSee(file));
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Debug, $"{ReadAsync} Error: {error.Message}");
            }
            return rstream;
        }

        public string? Read(string file, Encoding? encoding = null)
        {
            try
            {
                using FileStream fstream = new(file, FileMode.Open, FileAccess.Read);
                using StreamReader rstream = new(stream: fstream, encoding ?? EncodingSee(file));
                return rstream.ReadToEnd();
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Debug, $"Read Error: {error.Message}");
            }
            return null;
        }

        public ICollection<string> ReadLine(string file, Encoding? encoding = null)
        {
            ICollection<string> collections = [];
            using FileStream fstream = new(file, FileMode.Open, FileAccess.Read);
            using StreamReader rstream = new(fstream, encoding ?? EncodingSee(file));

            while (!rstream.EndOfStream)
            {
                string? line = rstream.ReadLine();
                if (line != null) collections.Add(line);
            }

            return collections;
        }

        public async Task ReadLineAsync(string file, ReceiveLine? receiveLine, Encoding? encoding = null)
        {
            string? line;
            using FileStream fstream = new(file, FileMode.Open, FileAccess.Read);
            using StreamReader rstream = new(stream: fstream, encoding ?? EncodingSee(file));
            while ((line = await rstream.ReadLineAsync()) != null)
            {
                receiveLine?.Invoke(line);
            }
        }

        public async Task<ICollection<string>> ReadLineAsync(string file, Encoding? encoding = null)
        {
            ICollection<string> collections = [];
            try
            {
                using FileStream fstream = new(file, FileMode.Open, FileAccess.Read);
                using StreamReader rstream = new(stream: fstream, encoding ?? EncodingSee(file));
                await Task.Run(async () =>
                {
                    while (!rstream.EndOfStream)
                    {
                        string? line = null;
                        try
                        {
                            line = await rstream.ReadLineAsync();
                        }
                        catch
                        {
                            line = null;
                        }
                        if (line != null) collections.Add(line);
                    }
                });
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Debug, $"ReadLineAsync {error.Message}");
            }
            return collections;
        }

        public async Task WriteAsync(string file, string? contet, Encoding? encoding = null)
        {
            byte[] byteContent;

            if (string.IsNullOrEmpty(contet)) 
            {
                byteContent = Encoding.UTF8.GetBytes(string.Empty);
            }
            else
            {
                byteContent = Encoding.UTF8.GetBytes(contet);
            }

            using FileStream fileStream = new (file, FileMode.Create, FileAccess.Write, FileShare.Read);

            await fileStream.WriteAsync(byteContent);

            fileStream.Flush();

        }

        public async Task<object?> GetAssembly(string? name = null)
        {

            string FullName = string.Empty;
            string FullNameContent = string.Empty;
            Assembly MyAssembly = Assembly.GetExecutingAssembly();
            ICollection<string> AssemblyNames = [];
            await Task.Run(async () =>
            {
                //  截取配置文件名，与参数文件名匹配
                foreach (var path in MyAssembly.GetManifestResourceNames().Where(x => x.Contains("DefaultConfig")))
                {
                    string[] splitNames = path.Split('.');
                    if (splitNames.Length >= 2)
                    {
                        IEnumerable<string> SkipNames = splitNames.Skip(splitNames.Length - 2);

                        if (!string.IsNullOrEmpty(name))
                        {
                            if (name.Contains('.'))
                            {
                                string[] Names = name.Split('.');
                                if (SkipNames.Where(x => Names.Contains(x)).Count() == Names.Length)
                                {
                                    FullName = path;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            AssemblyNames.Add(SkipNames.Join("."));
                        }
                    }
                }
                if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(FullName))
                {
                    using Stream? stream = MyAssembly.GetManifestResourceStream(FullName);
                    if (stream is not null)
                    {
                        using StreamReader reader = new(stream);
                        FullNameContent = await reader.ReadToEndAsync();
                    }
                }
            });

            if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(FullNameContent))
            {
                return FullNameContent;
            }
            else if (string.IsNullOrEmpty(name))
            {
                return AssemblyNames;
            }
            return null;
        }

        public string? CreateDir(string dir)
        {
            if (Directory.Exists(dir)) return dir;
            List<string> splitPath = [.. RegExp.RegExpSplitPath().Split(dir)];
            if (splitPath.Count > 0)
            {
                string combination = string.Empty;
                for (int digit = 1; digit <= splitPath.Count; digit++)
                {
                    combination = string.Join("/", splitPath.GetRange(0, digit)); 
                    try
                    {
                        if (!Directory.Exists(combination)) Directory.CreateDirectory(combination);
                    }
                    catch
                    {
                        continue;
                    }
                }
                if (Directory.Exists(combination)) return combination;
            }
            return null;
        }

        public string? CreateFile(string file)
        {
            if (File.Exists(file)) return file;
            List<string> splitPath = [.. RegExp.RegExpSplitPath().Split(file)];
            string dir = string.Join("/", splitPath.GetRange(0, splitPath.Count - 1));
            file = string.Join("/", splitPath.GetRange(0, splitPath.Count));
            if (CreateDir(dir) is not null)
            {
                try
                {
                    using FileStream _File = File.Create(file);
 
                    if (File.Exists(file))
                    {
                        return file;
                    }
                }
                catch (Exception error)
                {
                    Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
                    return null;
                }
            }
            return null;
        }

        public string GetDir(string file)
        {
            if (!File.Exists(file)) return string.Empty;
            List<string> splitPath = [.. RegExp.RegExpSplitPath().Split(file)];
            return string.Join("/", splitPath.GetRange(0, splitPath.Count - 1));
        }

        public bool OpenFile(string path)
        {
            ProcessStartInfo customStartInfo = new()
            {
                FileName = path,   //  文件路径
                UseShellExecute = true,                     //  使用系统Shell打开（依赖文件关联）
                Verb = "open"                               //  明确指定"打开"操作
            };
            if (Process.Start(customStartInfo) is not null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public async Task<ICollection<string>> GetLocalFilesAsync(LocalFileFilterOptions Options)
        {
            if (TokenSource.IsCancellationRequested) TokenSource = new CancellationTokenSource();

            ConcurrentBag<string> files = [];

            var ParallelOption = new ParallelOptions
            {
                CancellationToken = TokenSource.Token,
                MaxDegreeOfParallelism = 3
            };

            try
            {
                await Task.Run(() =>
                {
                    _ = Parallel.ForEach(Options.Filter_Paths, ParallelOption, path =>
                    {
                        if (System.IO.Path.Exists(path))
                        {
                            TokenSource.Token.ThrowIfCancellationRequested();
                            ParallelOption.CancellationToken.ThrowIfCancellationRequested();

                            IEnumerable<string> receives = Directory.EnumerateFiles(path, ".", SearchOption.AllDirectories)
                            .AsParallel()
                            .WithCancellation(TokenSource.Token);

                            foreach (var receive in receives)
                            {
                                if (ConditionMatch(receive, Options.Filter_Keyworks, Options.Filter_Extensions, Options.Filter_Mode))
                                {
                                    TokenSource.Token.ThrowIfCancellationRequested();
                                    Options.Progress?.Report((receive, TokenSource));
                                    files.Add(receive);
                                }
                            }
                        }
                        else
                        {
                            Options.Progress?.Report((string.Empty, TokenSource));
                        }
                    });

                }, TokenSource.Token);

            }
            catch (OperationCanceledException)
            {
                TokenSource.Cancel();
            }
            return [.. files];
        }

        private bool ConditionMatch(string file, ICollection<string> keyworks, ICollection<string> extensions, LocalFileFilterOptions.Mode mode)
        {
            sbyte total = 0;
            sbyte count = 0;
            bool ckey = keyworks.Count > 0;
            bool cexd = extensions.Count > 0;
            if (ckey) total++;
            if (cexd) total++;
            if (ckey)
            {
                foreach (var keywork in keyworks)
                {
                    TokenSource.Token.ThrowIfCancellationRequested();
                    if (mode == LocalFileFilterOptions.Mode.Exact)
                    {
                        if (file.Contains(keywork)) count++;
                    }
                    else if (mode == LocalFileFilterOptions.Mode.Vague)
                    {
                        if (file.Contains(keywork, StringComparison.CurrentCultureIgnoreCase)) count++;
                    }
                }
            }
            if (cexd)
            {
                foreach (var exd in extensions)
                {
                    TokenSource.Token.ThrowIfCancellationRequested();
                    if (mode == LocalFileFilterOptions.Mode.Exact)
                    {
                        if (GetSuffix(file).Contains(exd)) count++;
                    }
                    else if (mode == LocalFileFilterOptions.Mode.Vague)
                    {
                        if (GetSuffix(file).Contains(exd, StringComparison.CurrentCultureIgnoreCase)) count++;
                    }
                }
            }
            if (count == total)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public string GetSuffix(string file)
        {
            return System.IO.Path.GetExtension(file);
        }

        public string GetSimpleName(string file)
        {
            return RegExp.RegExpSplitPath().Split(file).Last();
        }

        public string GetSlippyName(string file)
        {
            string LastElement = RegExp.RegExpSplitPath().Split(file).Last();
            string? Extrnsion = System.IO.Path.GetExtension(file);
            if (Extrnsion is not null)
            {
                return LastElement[..(LastElement.LastIndexOf(Extrnsion))];
            }
            return string.Empty;
        }

        public bool IsDir(string dir)
        {
            if (Directory.Exists(dir))
            {
                return true;
            }
            return false;
        }

        public bool IsFile(string file)
        {
            if (File.Exists(file))
            {
                return true;
            }
            return false;
        }

        public string RegistryAction(int type, RegistryKey regkey, string path, string name, string key, string value)
        {
            string getValue = "";

            try
            {
                path = Path.Combine(path, name);
                RegistryKey? regKey = regkey.OpenSubKey(path, true);
                switch (type)
                {
                    case 0:
                        regKey ??= Registry.CurrentUser.CreateSubKey(path);
                        regKey.SetValue(key, value);
                        regKey.Close();
                        break;

                    case 1:
                        if (regKey is not null)
                        {
                            object? regvalue = regKey.GetValue(key);
                            if (regvalue is not null)
                            {
                                getValue = regvalue.ToString() ?? string.Empty;
                            }
                            regKey.Close();
                        }
                        break;

                    case 2:
                        if (regKey != null)
                        {
                            regKey.DeleteValue(key, false);
                            regKey.Close();
                        }
                        break;

                    default:
                        regKey ??= Registry.CurrentUser.CreateSubKey(path);
                        regKey.SetValue(key, value);
                        regKey.Close();
                        break;

                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
            return getValue;
        }

        public async Task<Dictionary<string, Dictionary<string, string>>> ReadIniAsync(string file)
        {
            string content = await File.ReadAllTextAsync(file);
            Dictionary<string, Dictionary<string, string>> IniMap = [];
            Dictionary<int, string> mainKeyMap = content.MatchAll("\\[(.*?)\\]", 1); //  匹配主键
            Dictionary<int, string> mainValueMap = content.MatchAll("([^\r\n\\s]+\\s*=\\s*[^\r\n\\s]*)", 1); //  匹配Value值
            try
            {
                if (mainKeyMap is not null)
                {
                    await Task.Run(() =>
                    {
                        int mainCount = mainKeyMap.Count;
                        for (int index = 0; index < mainCount; index++)
                        {
                            KeyValuePair<int, string> mainkeyPair = mainKeyMap.ElementAt(index);
                            string _mainKey = mainkeyPair.Value;
                            int _index = mainkeyPair.Key;

                            Dictionary<string, string> SectionMap = [];
                            ICollection<string> ExpectValues = [];
                            if (index + 1 < mainCount)
                            {
                                //  非最后行则根据索引来限定获取value值，以保证在所属主键范围
                                KeyValuePair<int, string> beginkeyPair = mainKeyMap.ElementAt(index + 1);
                                ExpectValues = [.. mainValueMap.Where(x => x.Key > _index && x.Key < beginkeyPair.Key).Select(x => x.Value)];
                            }
                            else
                            {
                                ExpectValues = [.. mainValueMap.Where(x => x.Key > _index).Select(x => x.Value)]; //  最后行直接往后取索引内容
                            }

                            foreach (var v in ExpectValues)
                            {
                                if (v.Contains('='))
                                {
                                    string[] split_value = v.Split('=', 2);
                                    if (split_value.Length == 2)
                                    {
                                        string _assertValue = split_value[1];
                                        if (_assertValue == "None") _assertValue = string.Empty;
                                        if (SectionMap.ContainsKey(split_value[0]))
                                        {
                                            SectionMap[split_value[0]] = split_value[1];
                                        }
                                        else
                                        {
                                            SectionMap.Add(split_value[0], split_value[1]);
                                        }
                                    }
                                }
                            }
                            IniMap[_mainKey] = SectionMap;
                        }
                    });
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
            return IniMap;
        }

        public async Task WriteIniAsync(string file, string ownerKey, string key, object value)
        {
            await WriteIniAsync(file, ownerKey, new Dictionary<string, string> { { key, value.GetSafetyChar() } });
        }

        public async Task WriteIniAsync(string file, string ownerKey, Dictionary<string, string>? updatesMap)
        {
            string content = string.Empty;
            try
            {
                content = await File.ReadAllTextAsync(file);
            }
            catch (Exception error1)
            {
                try
                {
                    content = (await ReadLineAsync(file)).Join("");
                    Logger.Print(RuntimeLog.LogType.Error, "ReadAllTextAsync: " + error1.Message);
                }
                catch (Exception error2)
                {
                    Logger.Print(RuntimeLog.LogType.Error, "ReadLineAsync: " + error2.Message);
                }
            }
            Dictionary<int, string> mainKeyvalueMap = content.MatchAll("\\[(.*?)\\]", 1);
            Dictionary<int, string> childKeyValueMap = content.MatchAll("([^\r\n\\s]+\\s*=\\s*[^\r\n\\s]*)+");

            try
            {
                if (mainKeyvalueMap.ContainsValue(ownerKey.Trim()))
                {
                    ICollection<KeyValuePair<int, string>> mainKeyvalues = [.. mainKeyvalueMap.OrderBy(x => x.Key)];
                    (int, int) ideaRange = (-1, -1);
                    foreach (var pair in mainKeyvalues) // 获取有效区间
                    {
                        if (pair.Value.Trim() == ownerKey.Trim())
                        {
                            ideaRange.Item1 = pair.Key - 1;
                        }
                        else if (ideaRange.Item1 != -1)
                        {
                            ideaRange.Item2 = pair.Key - 1;
                            break;
                        }
                    }

                    //  区分只有单一项的情况，只有单一项时，没有闭合索引，因此做区分处理，保证都可以正常的获取到预期的值
                    await Task.Run(async () =>
                    {
                        ICollection<string> ExpectValues = [];
                        string SectionContent = string.Empty;

                        if (ideaRange.Item2 == -1) // 等于 -1 即意味着文档没有字符长度，是空的或者是最后一项，这是后直接往后获取即可
                        {
                            ExpectValues = [.. childKeyValueMap
                            .Where(x => x.Key > ideaRange.Item1)
                            .OrderBy(x=>x.Key)
                            .Select(x => x.Value)];

                            SectionContent = "\r\n" + content[ideaRange.Item1..];
                        }
                        else
                        {
                            if (ideaRange.Item1 < ideaRange.Item2)
                            {
                                ExpectValues = [.. childKeyValueMap
                                .Where(x => x.Key > ideaRange.Item1 && x.Key < ideaRange.Item2)
                                .OrderBy(x=>x.Key)
                                .Select(x => x.Value)];

                                SectionContent = content[ideaRange.Item1..ideaRange.Item2];
                            }
                        }

                        string ActionContent = SectionContent; // 重新赋值，当前需要修改 actionContent 至预期效果即可
                        foreach (var key in ExpectValues)
                        {
                            if (key.Contains('='))
                            {
                                string[] split_value = key.Split('=', 2);

                                if (split_value.Length == 2 && updatesMap != null)
                                {
                                    if (updatesMap.TryGetValue(split_value[0].Trim(), out string? _updvalue))
                                    {
                                        ActionContent = ActionContent.Replace(key, $"{split_value[0]}={_updvalue}");
                                        updatesMap.Remove(split_value[0].Trim());
                                    }
                                }
                            }
                        }

                        //  适配为空的情况，为空则赋值空白值
                        if (updatesMap == null)
                        {
                            ActionContent = string.Empty;
                        }
                        else
                        {
                            foreach (var suplus in updatesMap)
                            {
                                ActionContent += $"{suplus.Key}={suplus.Value}\r\n";
                            }
                        }

                        //  存在内容时再追加换行
                        if (ActionContent.Length > 0)
                        {
                            ActionContent = RegExp.RegExpEmpty4().Replace(ActionContent, "\r\n") + "\r\n";
                        }
                        else
                        {
                            ActionContent = string.Empty;
                        }

                        await WriteAsync(file, content.Replace(SectionContent, ActionContent));
                    });
                }
                else
                {
                    content = RegExp.RegExpEmpty4().Replace(content, "\r\n");

                    string WriteContent = content + "\r\n";

                    WriteContent += $"[{ownerKey}]\r\n";

                    if (updatesMap != null)
                    {
                        foreach (var groups in updatesMap)
                        {
                            WriteContent += $"{groups.Key}={groups.Value}\r\n";
                        }
                    }
                    await WriteAsync(file, WriteContent);
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"WriteIniAsync Error: {error.Message}");
            }
        }

        private readonly object _syncobj = new();

        public bool _disposed = false;
        /// <summary>
        /// release occupy source
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            bool _synclock = false;

            try
            {
                if (!_disposed)
                {
                    Monitor.Enter(_syncobj, ref _synclock);
                    TokenSource?.Dispose();
                    _disposed = true;
                }
            }
            finally
            {
                if (_synclock) Monitor.Exit(_syncobj);
                Logger.Debug($"{this} -> release, where lock stat {_synclock}");
            }
        }

        ~DirFileServer()
        {
            Dispose(false);
        }
    }

    public static class Extendsion
    {
        private readonly static ILogger Logger = Serilog.Log.Logger.ForContext<Exception>();

        public static void Reteller<TValue>(this ICollection<TValue> source, ICollection<TValue> Items, bool IsAppend = false)
        {
            if (!IsAppend) source.Clear();

            foreach(var item in Items)
            {
                source.Add(item);
            }
        }

        public static void Reteller<TValue>(this ICollection<TValue> source, IEnumerable<TValue> Items, bool IsAppend = false)
        {
            if (!IsAppend) source.Clear();

            foreach (var item in Items)
            {
                source.Add(item);
            }
        }

        public static TValue? Reteller<TValue>(this ICollection<TValue> source, int Index)
        {
            if (Index < source.Count && Index >= 0)
            {
                return source.ElementAt(Index);
            }

            return default;
        }

        public static TValue? Reteller<TValue>(this IEnumerable<TValue> source, int Index)
        {
            if (Index < source.Count())
            {
                return source.ElementAt(Index);
            }

            return default;
        }

        public static void Reteller<TKey, TValue>(this IDictionary<TKey, TValue> source, IDictionary<TKey, TValue> Dict, bool IsAppend = false)
        {
            if (!IsAppend) source.Clear();

            foreach (var pair in Dict)
            {
                source.Add(pair);
            }
        }

        public static async Task<ICollection<string>> Com(this ManagementObjectSearcher source)
        {

            ICollection<string> Collection = [];

            await Task.Run(() =>
            {
                if (source is null) throw new ArgumentException("data source error");
                ConfigSectionModel.SerialConfigInfoMap.Com.SerialComNameMap.Clear();
                foreach (ManagementBaseObject coml in source.Get())
                {
                    string Cominfo = coml["Name"].ToString() ?? string.Empty;
                    if (Cominfo != null)
                    {
                        string result = RegExp.RegExpSerialCom().Match(Cominfo).Value;
                        if (result != null && result.Length > 0)
                        {
                            Collection.Add(Cominfo);
                            if (!ConfigSectionModel.SerialConfigInfoMap.Com.SerialComNameMap.ContainsKey(Cominfo))
                            {
                                ConfigSectionModel.SerialConfigInfoMap.Com.SerialComNameMap.TryAdd(Cominfo, result);
                            }
                        }
                    }
                }
            });

            return Collection;
        }

        public static void Print(this ILogger logger, LogType Type, params object[] args)
        {
            switch (Type)
            {
                case LogType.Fatal:

                    logger.Fatal(string.Join("  ", args));

                    break;
                case LogType.Error:

                    logger.Error(string.Join("  ", args));

                    break;
                case LogType.Warning:

                    logger.Warning(string.Join("  ", args));

                    break;
                case LogType.Debug:

                    logger.Debug(string.Join("  ", args));

                    break;
                case LogType.Info:

                    logger.Information(string.Join("  ", args));

                    break;
            }
        }

        public static void Print(this ILogger logger, LogType Type, object[] args, 
                                [CallerLineNumber] int Line = 0,
                                [CallerFilePath] string path = "",
                                [CallerMemberName] string name = "")
        {
            Print(logger, Type, $" {Line} {Path.GetFileName(path)} {name} " + string.Join("  ", args));
        }

        public static SolidColorBrush FindSolidBrush(this string source)
        {
            SolidColorBrush? seek = source.FindSource<SolidColorBrush>();
            if (seek is not null)
            {
                return seek;
            }
            
            return new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));
        }

        public static Color GetColor(this string source)
        {
            object? Result = ColorConverter.ConvertFromString(source);
            if (Result is not null and Color ResultColor)
            {
                return ResultColor;
            }

            return Color.FromArgb(0, 0, 0, 0);
        }

        public static TEnum? GetType<TEnum>(this string name)
        {
            Array EnumArray = Enum.GetValues(typeof(TEnum));

            TEnum? result = default;

            foreach(var i in EnumArray)
            {
                if (i is TEnum TEnumType && $"{TEnumType}" == name)
                {
                    result = TEnumType;
                    break;
                }
            }
            return result;
        }

        public static T? FindSource<T>(this string source)
        {
            if (Application.Current.Resources[source] is T d)
            {
                return d;
            }
            return default;
        }

        public static Dictionary<int, string> MatchAll(this string source, string regexp, int groupIndex = -1)
        {
            Dictionary<int, string> MatchsResultMap = [];
            try
            {
                MatchCollection matchCollection = Regex.Matches(source, regexp);
                void Add(System.Text.RegularExpressions.Match match, int index)
                {
                    Group group = match.Groups[index];
                    string _value = group.Value;
                    int _index = group.Index;
                    MatchsResultMap.TryAdd(_index, _value);
                }

                foreach (System.Text.RegularExpressions.Match match in matchCollection)
                {
                    if (match.Groups.Count > 0)
                    {
                        if (groupIndex != -1 && groupIndex < match.Groups.Count)
                        {
                            Add(match, groupIndex);
                        }
                        else
                        {
                            Add(match, 0);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
            } 
            catch
            {
                MatchsResultMap.Clear();
            }
            return MatchsResultMap;
        }

        public static string GetDesorderly(this int source)
        {
            byte[] bytes = new byte[source];
            using var random = RandomNumberGenerator.Create();
            random.GetBytes(bytes);
            return RegExp.RegExpSpecial().Replace(BitConverter.ToString(bytes), string.Empty);
        }
        
        public static string GetDesorderly(this ICollection<string> source)
        {
            string idkey = string.Empty;
            try
            {
                int resetCount = 0;
                int maxLen = source.Select(x => x.Length).Max() / 2;
                while (true)
                {
                    idkey = maxLen.GetDesorderly();
                    if (resetCount >= 400)
                    {
                        maxLen++;
                        resetCount = 0;
                    }

                    if (!source.Contains(idkey)) break;

                    resetCount++;
                }
            } 
            catch (Exception error)
            {
                Logger.Print(LogType.Error, error.Message);
            }
            return idkey;
        }

        public static string GetDesorderly(this ICollection<object> source)
        {
            List<string> ConvertColls = [..source.Select(x => x.GetSafetyChar())];

            return GetDesorderly(ConvertColls);
        }

        public static string GetDesorderlyBlue(this int source, bool isScan = false)
        {
            byte[] bytes = new byte[source];
            using var random = RandomNumberGenerator.Create();
            random.GetBytes(bytes);
            if (isScan)
            {
                return RegExp.RegExpSpecial().Replace(BitConverter.ToString(bytes), "-");
            }
            else
            {
                return RegExp.RegExpSpecial().Replace(BitConverter.ToString(bytes), ":");
            }
        }

        public static ICollection<TKType> GetSafetyKey<TKType, TVType>(this IDictionary<TKType, TVType> source, TVType value)
        {
            ICollection<TKType> Keys = [];

            foreach(KeyValuePair<TKType, TVType> pair in source)
            {
                if (pair.Value is not null && pair.Value.Equals(value))
                {
                    Keys.Add(pair.Key);
                }
            }
            return Keys;
        }

        public static string Join(this IEnumerable<string> source, string space, bool isSqlColumn = false, ICollection<string>? excepcteds = null)
        {
            string _string = string.Empty;
            if (excepcteds is not null) source = [.. source.Where(x => !excepcteds.Contains(x))];
            ICollection<string> sources = [.. source];
            if (sources.Count > 1)
            {
                int index = 0;
                foreach (var single in sources)
                {
                    string _single = single;

                    if (isSqlColumn)
                    {
                        _single = $"'{single}'";
                    }

                    if (index < sources.Count - 1)
                    {
                        _string += _single + space;
                    }
                    else
                    {
                        _string += _single;
                    }
                    index++;
                }
            }
            else
            {
                if (sources.Count == 1) _string = sources.GetSafetyChar(0);
            }
            return _string;
        }

        public static (T?, T?, ICollection<T?>)? GetDifference<T>(this IEnumerable<T> datas)
        {
            return GetDifference<T?>([.. datas]);
        }

        public static (T?, T?, ICollection<T?>)? GetDifference<T>(this IList<T> datas)
        {
            ArgumentNullException.ThrowIfNull(datas, nameof(datas));

            int index = 0;
            int common_place = -1;
            var conver = TypeDescriptor.GetConverter(typeof(T));
            foreach (var data in datas)
            {
                if (index > 0)
                {
                    T p_element = datas.ElementAt(index - 1);
                    T c_element = datas.ElementAt(index);
                    if (p_element is not null && c_element is not null)
                    {
                        string previous = p_element.GetSafetyChar();
                        string current = c_element.GetSafetyChar();
                        for (int place = 0; place < current.Length; place++)
                        {
                            if (current[place] != previous[place])
                            {
                                //  需要获取更多的位数来进行兼容有差异的部分，因此判断 common_place > place，确保差异部分展示完整
                                if (common_place == -1 || common_place > place)
                                {
                                    common_place = place;
                                }
                                break;
                            }
                        }
                    }
                }
                index++;
            }

            if (common_place > 0)
            {
                ICollection<T?> result =
                    [
                        .. datas.Select(x =>
                        {
                            if (x is not null)
                            {
                                if (x?.GetSafetyChar().Length > common_place)
                                {
                                    string? value = x?.GetSafetyChar()[common_place..];
                                    if (value is not null)
                                    {
                                        object? _obj = conver.ConvertFromString(value);
                                        if (_obj is not null)
                                        {
                                            return (T)_obj;
                                        } else return default;
                                    } else return default;
                                }
                                else
                                {
                                    if (conver.ConvertFromString("这是一条异常数据") is not null and object _EmptyHint)
                                    {
                                        return (T)_EmptyHint;
                                    }else
                                    {
                                        return default;
                                    }
                                }
                            } else return default;
                        })
                    ];
                return (result.First(), result.Last(), result);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// <para>wall 允许的最小字符位数，-1则不限制</para>
        /// </summary>
        /// <param name="data"></param>
        /// <param name="wall"></param>
        /// <returns></returns>
        public static ICollection<string> MatchTime(this string data, int wall = -1)
        {
            ICollection<string> result = [];
            foreach (Match match in RegExp.RegExpTimeDetetor().Matches(data))
            {
                string getMatch = match.Value;

                if (wall == -1)
                {
                    result.Add(getMatch);
                }
                else
                {
                    if (getMatch.Length >= wall) result.Add(getMatch);
                }
            }
            return result;
        }

        public static string ConvertDateFormat(this string date)
        {
            Dictionary<int, string> _relationMap = new()
            {
                { 0, "y" },
                { 1, "M" },
                { 2, "d" },
                { 3, "h" },
                { 4, "m" },
                { 5, "s" },
                { 6, "f" }
            };

            string pattern = string.Empty;
            int special_index = 0;
            string previous = string.Empty;

            foreach (var i in date)
            {
                string single = i.ToString();
                string MatchValue = RegExp.RegExpSpecial().Match(single).Value; //  匹配特殊字符
                if ((!string.IsNullOrEmpty(MatchValue) || i == '_') && previous != single)
                {
                    pattern += single;
                    special_index++;
                }
                else
                {
                    if (_relationMap.TryGetValue(special_index, out string? _char))
                    {
                        int Subindex = pattern.Length - 1;
                        string hourly = RegExp.RegExpNumber().Match(previous + single).Value;

                        if (_char == "h")
                        {
                            if (pattern.Length >= 2 &&
                                hourly.Length == 2 &&
                                int.TryParse(hourly, out int _hour) &&
                                _hour > 12)
                            {
                                pattern = pattern[..Subindex] + pattern[Subindex..].ToUpper();
                            }
                            pattern += _char.ToUpper();
                        }
                        else
                        {
                            pattern += _char;
                        }
                    }
                }
                previous = single;
            }
            return pattern;
        }

        /// <summary>
        /// <para>orign 0 left 1 right</para>
        /// </summary>
        /// <param name="source"></param>
        /// <param name="digit"></param>
        /// <param name="orign"></param>
        /// <param name="spm"></param>
        /// <returns></returns>
        public static string SubjoinString(this string source, int digit = -1, int orign = 0, string repeat = " ")
        {
            string Complete = string.Empty;
            if (digit != -1 && source.Length <= digit)
            {
                string Supplement = string.Concat(Enumerable.Repeat(repeat, digit - source.Length));

                if (orign == 0)
                {
                    Complete += Supplement + source;
                }
                else if (orign == 1)
                {
                    Complete += source + Supplement;
                }
            }
            return string.IsNullOrEmpty(Complete) ? source : Complete;
        }

        /// <summary>
        /// depth map is [0,1,2,3,4,5,6] map value [y,M,d,H,m,s,f], can depth arg 1-7
        /// </summary>
        /// <param name="date"></param>
        /// <param name="depth"></param>
        /// <returns></returns>
        public static (string, DateTime) ConvertDateFormat(this string date, int depth)
        {
            if (date is not null)
            {
                Dictionary<int, string> _relationMap = new()
                {
                    { 0, "y" },
                    { 1, "M" },
                    { 2, "d" },
                    { 3, "h" },
                    { 4, "m" },
                    { 5, "s" },
                    { 6, "f" }
                };
                int special_index = 0;
                string pattern = string.Empty;
                string previous = string.Empty;
                string datechars = string.Empty;

                foreach (var i in date)
                {
                    datechars = string.Concat(datechars, i);
                    string single = i.ToString();
                    string MatchValue = RegExp.RegExpSpecial().Match(single).Value; //  匹配特殊字符
                    if ((!string.IsNullOrEmpty(MatchValue) || i == '_') && previous != single)
                    {
                        pattern += single;
                        special_index++;
                    }
                    else
                    {
                        if (_relationMap.TryGetValue(special_index, out string? _char))
                        {
                            int Subindex = pattern.Length - 1;
                            string hourly = RegExp.RegExpNumber().Match(previous + single).Value;

                            if (_char == "h")
                            {
                                if (pattern.Length >= 2 &&
                                    hourly.Length == 2 &&
                                    int.TryParse(hourly, out int _hour) &&
                                    _hour > 12)
                                {
                                    pattern = pattern[..Subindex] + pattern[Subindex..].ToUpper();
                                }
                                pattern += _char.ToUpper();
                            }
                            else
                            {
                                pattern += _char;
                            }
                        }
                    }
                    if (special_index == depth) break;
                    previous = single;
                }

                if (DateTime.TryParseExact(datechars, pattern, CultureInfo.InvariantCulture,
                                           DateTimeStyles.None, out DateTime convert_date))
                {
                    return (datechars.Trim(), convert_date);
                }
            }
            return (string.Empty, DateTime.Now);
        }

        public static int LongToint(this long source)
        {
            return source > int.MaxValue ? int.MaxValue : (int)source;
        }

        public static string CurrentDir(this string source)
        {
            ArgumentNullException.ThrowIfNull(source, nameof(source));

            return Directory.GetCurrentDirectory();
        }

        public static string WrapWord(this string source)
        {
            Dictionary<int, string> MatchInfo = source.MatchAll("[\r\n|\n]");

            int maxIndex = MatchInfo.Keys.Count > 0 ? MatchInfo.Keys.Max() : -1;
            
            if (maxIndex != -1 && maxIndex >= source.Length - 2)
            {
                return source;
            }
            else
            {
                return source + "\r\n";
            }
        }

        public static string GetSafetyChar(this object source, bool isRegexp = false)
        {
            if (source != null)
            {
                if (isRegexp)
                {
                    if (source.ToString() is not null and string value)
                    {
                        return value.Replace(@"\\", @"\");
                    }
                }
                else
                {
                    return source?.ToString() ?? string.Empty;
                }
            }
            return string.Empty;
        }

        public static string GetXORcode(this string source)
        {
            byte[] sBytes = Encoding.ASCII.GetBytes(source);
            byte xorByte = 0x00;
            foreach(byte _byte in sBytes)
            {
                xorByte = Convert.ToByte(xorByte ^ _byte);
            }
            return xorByte.ToString();
        }

        public static T? GetSafetyChar<T>(this ObservableCollection<T> source, int index)
        {
            if (source.Count > 0 && source != null)
            {
                if (index >= source.Count)
                {
                    return source[^1];
                }
                else
                {
                    return source[index];
                }
            }
            else
            {
                return default;
            } 
        }

        public static string GetSafetyChar(this object[] source, int index)
        {
            if (source?.Length > index)
            {
                return source[index].GetSafetyChar();
            }
            else
            {
                return source?[^1].GetSafetyChar() ?? string.Empty;
            }
        }

        public static string GetSafetyChar(this IEnumerable<object> source, int index)
        {
            if (index >= 0) 
            {
                if (!source.Any())
                {
                    return string.Empty;
                }
                else if (index < source.Count())
                {
                    return source.ElementAt(index).GetSafetyChar();
                }
                else
                {
                    return source.ElementAt(^1)?.GetSafetyChar() ?? string.Empty;
                } 
            } else return string.Empty;
        }

        public static bool? GetSafetyBool(this IEnumerable<object> source, int index)
        {
            if (index >= 0)
            {
                if (!source.Any())
                {
                    return null;
                }
                else if (index < source.Count() && bool.TryParse(source.ElementAt(index).GetSafetyChar(), out bool _Bool))
                {
                    return _Bool;
                }
                else
                {
                    if (bool.TryParse(source.ElementAt(^1).GetSafetyChar(), out bool _dBool))
                    {
                        return _dBool;
                    }
                }
            }
            return null;
        }

        public static bool CanSafetyConvert(this FieldInfo source, string value, out object? push)
        {
            push = CanSafetyConvert(source.FieldType, value);
            return push is not null;
        }

        public static object? CanSafetyConvert(this Type source, object value)
        {
            if (source is not null)
            {
                try
                {
                    TypeConverter typeConverter = TypeDescriptor.GetConverter(source);
                    if (typeConverter.CanConvertFrom(typeof(string)))
                    {
                        if (typeConverter.ConvertFromString(value.GetSafetyChar()) is not null and object _value)
                        {
                            return _value;
                        }
                    }
                }
                catch
                {
                    return null;
                }
            }
            return null;
        }

        public static bool CanSafetyConvert(this PropertyInfo source, string value, out object? push)
        {
            push = CanSafetyConvert(source.PropertyType, value);
            return push is not null;
        }

        public static void SetGridWidget(this Grid layout, int row, int column, UIElement widget)
        {
            Grid.SetRow(widget, row);
            Grid.SetColumn(widget, column);
            layout.Children.Add(widget);
        }

        public static void SetGridWidget(this Grid layout, int row, int column, int rowspan, int columnspan, UIElement widget)
        {
            Grid.SetRow(widget, row);
            if (rowspan >= 1) Grid.SetRowSpan(widget, rowspan);
            Grid.SetColumn(widget, column);
            if (columnspan >= 1) Grid.SetColumnSpan(widget, columnspan);
            layout.Children.Add(widget);
        }

        public static void TakeGridRowWidget(this Grid layout, int DelRow)
        {
            ICollection<UIElement> DelElements = layout.GetGridRowWidget(DelRow);
            foreach (var element in DelElements)
            {
                layout.Children.Remove(element);
            }
            layout.RowDefinitions.RemoveAt(DelRow);

            // 优化，surplusRow < layout.RowDefinitions.Count 为旧代码，实际情况是，每行surplusRow - 1，因为总行数与实际布局行之间相差1，
            // 而旧的循环条件中，如最大行数为 7 时，布局行数为 0-6，旧条件因为需要 - 1来适配布局行数，则为 0 - 5，因此最后一行没有将所属行数
            // 纠正过来，其表现为当有新增行时，会将这最后一行覆盖掉
            for (int surplusRow = DelRow; surplusRow <= layout.RowDefinitions.Count; ++surplusRow)
            {
                ICollection<UIElement> SurplusElements = layout.GetGridRowWidget(surplusRow);
                foreach (var element in SurplusElements)
                {
                    if (element is not null)
                    {
                        Grid.SetRow(element, surplusRow - 1);
                    }
                }
            }
        }

        public static ICollection<UIElement> GetGridRowWidget(this Grid layout, int row)
        {
            return [..layout.Children.OfType<UIElement>().Where(unit => Grid.GetRow(unit) == row)] ;
        }

        public static TControlType? GetGridRowWidget<TControlType>(this Grid layout, int row, string name)
        {
            TControlType? _Control = default;
            foreach (var unit in layout.Children.OfType<UIElement>().Where(unit => Grid.GetRow(unit) == row))
            {
                if (unit is FrameworkElement Control)
                {
                    if (unit is TControlType keyUI && Control.Name == name)
                    {
                        _Control = keyUI;
                    }
                }
            }
            return _Control;
        }

        public static KeyValuePair<TKType, TVType>? GetGridRowPairWidget<TKType, TVType>(this Grid layout, int row, string keyName, string valueName)
        {
            TKType? kType = default;
            TVType? vType = default;
            foreach (var unit in layout.Children.OfType<UIElement>().Where(unit => Grid.GetRow(unit) == row))
            {
                if (unit is FrameworkElement Control)
                {
                    if (unit is TKType keyUI && Control.Name == keyName)
                    {
                        kType = keyUI;
                    }
                    else if (unit is TVType valueUI && Control.Name == valueName)
                    {
                        vType = valueUI;
                    }
                }
            }
            if (kType != null && vType != null)
            {
                return new KeyValuePair<TKType, TVType>(kType, vType);
            }
            else
            {
                return null;
            }
        }

        public static KeyValuePair<ICollection<KType>, ICollection<VType>>? GetGridRowPairWidget<KType, VType>(this Grid layout, int row, string[] keyNames, string[] valueNames)
        {
            ICollection<KType> KTypeList = [];
            ICollection<VType> VTypeList = [];

            foreach (var unit in layout.Children.OfType<FrameworkElement>().Where(unit => Grid.GetRow(unit) == row))
            {
                foreach (var i in keyNames)
                {
                    if (unit is KType keyUI && unit.Name == i)
                    {
                        KTypeList.Add(keyUI);
                    }
                }
                foreach (var i in valueNames)
                {
                    if (unit is VType valueUI && unit.Name == i)
                    {
                        VTypeList.Add(valueUI);
                    }
                }
            }
            if (KTypeList.Count != 0 && VTypeList.Count != 0)
            {
                return new KeyValuePair<ICollection<KType>, ICollection<VType>>(KTypeList, VTypeList);
            }
            else
            {
                return null;
            }
        }

        public static ICollection<UIElement> GetGridWidget(this Grid layout, int column)
        {
            ArgumentNullException.ThrowIfNull(layout, nameof(layout));

            ICollection<UIElement> Reuslt = [];

            foreach(var unit in layout.Children.OfType<UIElement>())
            {
                if (Grid.GetColumn(unit) == column)
                {
                    Reuslt.Add(unit);
                }
            }

            return Reuslt;
        }

        public static T? GetWidget<T>(this ICollection<UIElement> widgets, string key)
        {
            var filter = widgets.Where((widget) => widget is T && ((FrameworkElement)widget).Name == key).ToList();

            if (filter.Count > 0 && filter[0] is T excpect) return excpect;

            return default;
        }

        /// <summary>
        /// 1 - value valid ; 0 - value invalid ; surplus - all
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static ICollection<FieldInfo> GetFields(this object source, int type = 1)
        {

            return [..source.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
                                              .Where(bool (value) => {
                                                  if (type == 1)
                                                  {
                                                    return value.GetValue(source) != null;
                                                  }
                                                  else if (type == 0)
                                                  {
                                                      return value.GetValue(source) == null;
                                                  }
                                                  else{
                                                      return true;
                                                  }
                                              })];
        }

        public static ICollection<FieldInfo> GetFields(this Type source)
        {
            return [..source.GetFields(BindingFlags.Public | BindingFlags.Instance)];
        }

        public static FieldInfo? GetField(this object source, string name) {
            var findField = source.GetFields(2).Where(x => x.Name == name);
            if (findField.Any())
            {
                return findField.ElementAt(0);
            }
            else
            {
                return null;
            }
        }

        public static FieldInfo? GetField<Type>(this object source)
        {
            var findField = source.GetFields(2).Where(x => x.FieldType == typeof(Type));
            if (findField.Any())
            {
                return findField.ElementAt(0);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 1 - value valid ; 0 - value invalid ; surplus - all
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static ICollection<PropertyInfo> GetPropertys(this object source, int type = 1)
        {

            return [..source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                              .Where(bool (value) => {
                                                  if (type == 1)
                                                  {
                                                    return value.GetValue(source) is not null and string _value && !string.IsNullOrEmpty(_value) ;
                                                  }
                                                  else if (type == 0)
                                                  {
                                                      return value.GetValue(source) == null;
                                                  }
                                                  else{
                                                      return true;
                                                  }
                                              })];
        }

        public static ICollection<PropertyInfo> GetPropertys(this Type source, int type = 1)
        {

            return [..source.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                              .Where(bool (value) => {
                                                  if (type == 1)
                                                  {
                                                    return value.GetValue(source) != null;
                                                  }
                                                  else if (type == 0)
                                                  {
                                                      return value.GetValue(source) == null;
                                                  }
                                                  else{
                                                      return true;
                                                  }
                                              })];
        }

        public static PropertyInfo? GetProperty(this object source, string name)
        {
            var findField = source.GetPropertys(2).Where(x => x.Name == name);
            if (findField.Any())
            {
                return findField.ElementAt(0);
            }
            else
            {
                return null;
            }
        }

        public static T? FindNestVisualTreeObject<T>(this Control source, string name)
        {
            if (source.Template.FindName(name, source) is not null and T obj)
            {
                return obj;
            }
            return default;
        }

        /// <summary>
        /// encording to parent unit find the multi children visual tree
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="G"></typeparam>
        /// <param name="OriginSource"></param>
        /// <returns></returns>
        public static ICollection<TG> FindVisualUpObjects<T, TG>(this DependencyObject OriginSource) where T : DependencyObject
        {
            ICollection<TG> result = [];
            while (OriginSource != null)
            {
                if (OriginSource is T)
                {
                    LoopForVisualThree<T, TG>(OriginSource, result);
                    break;
                }
                else
                {
                    OriginSource = VisualTreeHelper.GetParent(OriginSource);
                }
            }
            return result;
        }


        /// <summary>
        /// encording to base unit find the parent visual tree
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="OriginSource"></param>
        /// <returns></returns>
        public static T? FindVisualUpObject<T>(this DependencyObject OriginSource) where T : DependencyObject
        {
            while (OriginSource != null)
            {
                if (OriginSource is T)
                {
                    return OriginSource as T;
                }
                else
                {
                    OriginSource = VisualTreeHelper.GetParent(OriginSource);
                }
            }
            return null;
        }

        private static void LoopForVisualThree<T, TG>(DependencyObject OriginSource, ICollection<TG> Receive, string? name = null)
        {
            if (OriginSource != null)
            {
                for (int index = 0; index < VisualTreeHelper.GetChildrenCount(OriginSource); index++)
                {
                    var children = VisualTreeHelper.GetChild(OriginSource, index);
                    if (children is TG RealSource)
                    {
                        if (string.IsNullOrEmpty(name))
                        {
                            Receive.Add(RealSource);
                        }
                        else if (!string.IsNullOrEmpty(name) && RealSource is FrameworkElement _FrameworkElement && _FrameworkElement.Name == name)
                        {
                            Receive.Add(RealSource);
                        }
                        else
                        {
                            LoopForVisualThree<TG, TG>(children, Receive);
                        }
                    }
                    else
                    {
                        LoopForVisualThree<T, TG>(children, Receive);
                    }
                }
            }
        }

        private static void LoopForVisualThree<T>(DependencyObject OriginSource, ref T? receive, string? name = null)
        {
            if (OriginSource != null)
            {
                for (int index = 0; index < VisualTreeHelper.GetChildrenCount(OriginSource); index++)
                {
                    var children = VisualTreeHelper.GetChild(OriginSource, index);
                    if (children is T RealSource)
                    {
                        if (string.IsNullOrEmpty(name))
                        {
                            receive = RealSource;
                        }
                        else if (!string.IsNullOrEmpty(name) && RealSource is FrameworkElement _FrameworkElement && _FrameworkElement.Name == name)
                        {
                            receive = RealSource;
                        }
                        else
                        {
                            LoopForVisualThree<T>(children, ref receive);
                        }
                        break;
                    }
                    else
                    {
                        LoopForVisualThree<T>(children, ref receive);
                    }
                }
            }
        }

        public static TCopyType? DeepCopy<TCopyType>(this TCopyType source)
        {
            try
            {
                JsonSerializerOptions options = new()
                {
                    IncludeFields = true,
                    DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
                };
                string Json = System.Text.Json.JsonSerializer.Serialize(source, options);
                TCopyType? convert = System.Text.Json.JsonSerializer.Deserialize<TCopyType>(Json, options);
                if (convert is not null and TCopyType _DeepValue)
                {
                    return _DeepValue;
                }
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, error.Message);
            }
            return default;
        }

        public static bool IsAbsoluteValidValue(this object source)
        {
            if (source is null)
            {
                return false;
            }
            else
            {
                if (source is string _string)
                {
                    return !string.IsNullOrEmpty(_string);
                }
                else if (source is bool _bool)
                {
                    return _bool;
                }
                else if (source is int _int)
                {
                    return _int > 0;
                }
                else if (source is double _double)
                {
                    return _double > 0;
                }
                else if (source is long _long)
                {
                    return _long > 0;
                }
                else if (source is Array _array)
                {
                    return _array.Length > 0;
                }
                else if (source is System.Collections.IEnumerable _IEnumerable)
                {
                    bool valid = false;
                    foreach (var i in _IEnumerable)
                    {
                        valid = true;
                        break;
                    }
                    return valid;
                }
            }
            return default;
        }

        public static string RepairstringFormat(this string source)
        {
            (char, char) pair = new('{', '}');
            if (source.Contains(pair.Item1) && source.Contains(pair.Item2))
            {
                string NewFormat = string.Empty;
                int t_index = 0;
                int v_index = 0;
                foreach (var _char in source)
                {
                    NewFormat += _char;
                    if (_char == pair.Item1)
                    {
                        if (source[t_index] == '{')
                        {
                            NewFormat += $"{v_index}";

                        }
                        v_index++;
                    }
                    t_index++;
                }
                return NewFormat;
            }
            return source;
        }

        public static object? DeepCopyObject<TIDeepType>(this TIDeepType source) where TIDeepType : class
        {
            object? Instance = Activator.CreateInstance(typeof(TIDeepType));

            BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;

            FieldInfo[] fields = typeof(TIDeepType).GetFields(Flags);

            PropertyInfo[] propertys = typeof(TIDeepType).GetProperties(Flags);

            (bool, bool) state = (false, false);
            int index = 0;
            while (true)
            {
                if (fields.Length > index)
                {
                    FieldInfo field = fields[index];
                    object? value = field.GetValue(source);
                    field.SetValue(Instance, value);

                }
                else
                {
                    state.Item1 = true;
                }

                if (fields.Length > index)
                {
                    PropertyInfo property = propertys[index];
                    object? value = property.GetValue(source);
                    property.SetValue(Instance, value);
                }
                else
                {
                    state.Item2 = true;
                }

                if (state.Item1 && state.Item2) break;

                index++;
            }

            return Instance;
        }
    }

    public class DenCryptoGraphicServer : IDenCryptoGraphicServer
    {
        public string DEbase64(string destring)
        {
            var decode = Convert.FromBase64String(destring);
            string replace = Encoding.UTF8.GetString(decode).Replace("_", "/").Replace("&", "+").Replace("#", "=");
            return replace;
        }

        public async Task<string> DeCryptoGraphic(string crypt, string password)
        {
            string cryptReulst = string.Empty;

            await Task.Run(() =>
            {
                byte[] byteCtypt = Convert.FromBase64String(crypt);
                int lenght = byteCtypt.Length;

                byte[] salt = new byte[16];
                byte[] iv = new byte[16];
                byte[] cryptbody = new byte[lenght - 32];
                Array.Copy(byteCtypt, 0, salt, 0, 16);
                Array.Copy(byteCtypt, 16, iv, 0, 16);
                Array.Copy(byteCtypt, 32, cryptbody, 0, lenght - 32);

                Rfc2898DeriveBytes rfc2898DeriveBytes = new
                (
                    password: password,
                    salt: salt,
                    iterations: 10000,
                    hashAlgorithm: HashAlgorithmName.SHA512
                );

                using System.Security.Cryptography.Aes AES = System.Security.Cryptography.Aes.Create();

                AES.Mode = CipherMode.CBC;

                AES.Key = rfc2898DeriveBytes.GetBytes(AES.KeySize / 8);

                AES.IV = iv;

                using MemoryStream memoryst = new(cryptbody);

                using CryptoStream cryptst = new(memoryst, AES.CreateDecryptor(), CryptoStreamMode.Read);

                using StreamReader reader = new(cryptst);

                cryptReulst = reader.ReadToEnd();
            });
            return cryptReulst;
        }

        public string ENbase64(string enstring)
        {
            byte[] encode = Encoding.UTF8.GetBytes(enstring);
            string replace = Convert.ToBase64String(encode).Replace("/", "_").Replace("+", "&").Replace("=", "#");
            return replace;
        }

        public async Task<string> EnCryptoGraphic(string content, string password)
        {
            string cryptReulst = string.Empty;

            await Task.Run(() =>
            {

                byte[] keys = new byte[16];

                byte[] IValue = new byte[16];

                using (var random = RandomNumberGenerator.Create())
                {
                    //  fill the random byte in new byte[]
                    random.GetBytes(keys); random.GetBytes(IValue);
                }

                //  prd key
                Rfc2898DeriveBytes rfc2898DeriveBytes = new
                (
                    password: password,
                    salt: keys,
                    iterations: 10000,
                    hashAlgorithm: HashAlgorithmName.SHA512
                );

                using var AES = System.Security.Cryptography.Aes.Create();
                //  输出长度：512位(64字节)
                //  用途：用于密码派生(PBKDF2)时的哈希计算
                //  作用：将密码和盐值转换为固定长度的哈希值
                //  与AES的关系：仅用于密钥派生,不影响AES本身的参数
                //  AES 标准支持 128位、192位和 256位,取决于用了什么类型的哈希算法
                AES.Mode = CipherMode.CBC;

                AES.Key = rfc2898DeriveBytes.GetBytes(AES.KeySize / 8);
                //  固定128位 / 8 16字节
                AES.IV = IValue;

                using MemoryStream menory = new();

                menory.Write(keys, 0, 16);

                menory.Write(IValue, 0, 16);

                //  创建加密流,参数为 内存流 和已经设置好参数的加密机
                using CryptoStream crypt = new(menory, AES.CreateEncryptor(), CryptoStreamMode.Write);

                crypt.Write(Encoding.UTF8.GetBytes(content), 0, content.Length);

                crypt.Close();

                cryptReulst = Convert.ToBase64String(menory.ToArray());
            });
            return cryptReulst;

        }
    }

    public class ActivityDetetorServer : IActivityDetetorServer
    {
        public delegate void OpenUIElement(Dictionary<string, WeakReference<FrameworkElement>> IndependentMap);
        private OpenUIElement? UIElementDelegate;
        private readonly IDataBaseServer DatabaseServer;
        private readonly IDirFileServer DirFileServer;
        private readonly Dictionary<string, WeakReference<FrameworkElement>> IndependentMap = [];
        private readonly ILogger Logger = Serilog.Log.Logger.ForContext<ActivityDetetorServer>();

        public ActivityDetetorServer()
        {
            App MyApp = (App)System.Windows.Application.Current;
            DatabaseServer = MyApp.ServiceProvider.GetRequiredService<IDataBaseServer>();
            DirFileServer = MyApp.ServiceProvider.GetRequiredService<IDirFileServer>();
        }

        public async Task<object?> AutoFindDim(OrderFilterCondition Condition)
        {
            if (DatabaseServer.GetDBIdentify() == DB.DB_TYPE.DB_Cloud)
            {
                return await WorkOrderCloudDimMatch(Condition);
            }

            else if (DatabaseServer.GetDBIdentify() == DB.DB_TYPE.DB_Local)
            {
                return await WorkOrderLocalDimMatch(Condition);
            }
            else
            {
                return null;
            }
        }

        public async Task<Supabase.Postgrest.Responses.ModeledResponse<WorkOrderUnfold>?> WorkOrderCloudDimMatch(OrderFilterCondition Condition)
        {
            Supabase.Postgrest.Responses.ModeledResponse<WorkOrderUnfold>? unfoldResponse = null;

            if (DatabaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
            {
                Supabase.Interfaces.ISupabaseTable<WorkOrderUnfold, Supabase.Realtime.RealtimeChannel>? Query = GetCloudFilterQuery(Condition.FilterConditions);
                if (Query != null)
                {
                    if (Condition.Filter_isSimpleQuery)
                    {
                        if (Condition.FilterRange is null || (Condition.FilterRange is not null &&
                            Condition.FilterRange.Value.Item1 < Condition.FilterRange.Value.Item2))
                        {
                            unfoldResponse = await Query
                            .Select(x => new object[] { x.Sn, x.Id, x.Imei, x.BlueMac, x.WorkorderNum })
                            .Order("imei", Supabase.Postgrest.Constants.Ordering.Ascending)
                            .Get();
                        }
                        else if (Condition.FilterRange is not null)
                        {
                            int start = Condition.FilterRange.Value.Item1.LongToint();
                            int end = Condition.FilterRange.Value.Item2.LongToint();

                            unfoldResponse = await Query
                           .Range(start, end)
                           .Select(x => new object[] { x.Sn, x.Id, x.Imei, x.BlueMac })
                           .Order("imei", Supabase.Postgrest.Constants.Ordering.Ascending)
                           .Get();
                        }
                    }
                    else
                    {
                        if (Condition.FilterRange is null || (Condition.FilterRange is not null &&
                            Condition.FilterRange.Value.Item1 > Condition.FilterRange.Value.Item2))
                        {
                            unfoldResponse = await Query
                            .Order("imei", Supabase.Postgrest.Constants.Ordering.Ascending)
                            .Get();
                        }
                        else if (Condition.FilterRange is not null)
                        {
                            int start = Condition.FilterRange.Value.Item1.LongToint();
                            int end = Condition.FilterRange.Value.Item2.LongToint();

                            unfoldResponse = await Query
                           .Range(start, end)
                           .Order("imei", Supabase.Postgrest.Constants.Ordering.Ascending)
                           .Get();
                        }
                    }
                }
            }
            if (unfoldResponse?.Models.Count > 0)
            {
                return unfoldResponse;
            }
            else
            {
                return null;
            }
        }

        public async Task<Dictionary<string, ICollection<object>>?> WorkOrderLocalDimMatch(OrderFilterCondition Condition)
        {
            string Range;
            if (Condition.FilterRange is null)
            {
                Range = "";
            }
            else
            {
                Range = $"LIMIT {Condition.FilterRange.Value.Item2 - Condition.FilterRange.Value.Item1} OFFSET {Condition.FilterRange.Value.Item1}";
            }

            int FilterTarget = Condition.Filter_isSimpleQuery switch
            {
                true => 0,
                false => 1
            };

            string Sql = $"{GetLocalFilterQuerySql(Condition.FilterConditions, FilterTarget)} {Range}";

            SqliteExceuteResult? ExceuteResult = await DatabaseServer.LocalDBQueryFree(Sql);

            if (ExceuteResult is not null &&
                ExceuteResult.ErrorHint is null &&
                ExceuteResult.Result.Count > 0 &&
                ExceuteResult.Result.TryGetValue(Sql, out var tableDataMap))
            {
                return tableDataMap;
            }
            return null;
        }

        public Supabase.Interfaces.ISupabaseTable<WorkOrderUnfold, Supabase.Realtime.RealtimeChannel>? GetCloudFilterQuery(ICollection<OrderFilterCondition.Condition> Conditions)
        {
            if (DatabaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
            {
                Supabase.Interfaces.ISupabaseTable<WorkOrderUnfold, Supabase.Realtime.RealtimeChannel> Query = CloudDB.From<WorkOrderUnfold>();

                foreach (var unit in Conditions)
                {
                    string mainField = unit.FilterFieldType switch
                    {
                        OrderFilterCondition.FieldType.IMEI => "imei",
                        OrderFilterCondition.FieldType.SN => "sn",
                        OrderFilterCondition.FieldType.BLUE => "blue_mac",
                        OrderFilterCondition.FieldType.DOID => "id",
                        OrderFilterCondition.FieldType.ORDER => "workorder_num",
                        _ => "imei",
                    };
                    Query.Filter(mainField, Supabase.Postgrest.Constants.Operator.Like, $"%{unit.FilterContent}%");
                }
                return Query;
            }
            return null;
        }

        public string GetLocalFilterQuerySql(ICollection<OrderFilterCondition.Condition> Conditions, int target = 0)
        {
            string Fields = string.Empty;
            ICollection<string> conditions = [];
            foreach (var condition in Conditions)
            {
                conditions.Add($"{GetWorkorderRealfieldName(condition.FilterFieldType)} LIKE '%{condition.FilterContent}%'");
            }

            if (target == 0)
            {
                Fields = "sn,imei,id,blue_mac,workorder_num";
            }
            else if (target == 1)
            {
                Fields = "*";
            }
            else if (target == 2)
            {
                Fields = "COUNT(*)";
            }

            string filter = conditions.Join(" and ");

            if (string.IsNullOrEmpty(filter)) 
            {
                return $"SELECT {Fields} FROM workorder_unfold";
            }
            else
            {
                return $"SELECT {Fields} FROM workorder_unfold WHERE {filter}";
            }
        }

        private static string GetWorkorderRealfieldName(OrderFilterCondition.FieldType FieldType)
        {
            string RealFieldName = FieldType switch
            {
                OrderFilterCondition.FieldType.IMEI => "imei",
                OrderFilterCondition.FieldType.SN => "sn",
                OrderFilterCondition.FieldType.DOID => "id",
                OrderFilterCondition.FieldType.BLUE => "blue_mac",
                OrderFilterCondition.FieldType.ORDER => "workorder_num",
                _ => "imei",
            };

            return RealFieldName;
        }

        public OrderFilterCondition.FieldType GetWorkOrderFieldType(string name)
        {
            Enum.GetValues(typeof(OrderFilterCondition.FieldType));

            OrderFilterCondition.FieldType FieldType = name.GetType<OrderFilterCondition.FieldType>();

            return FieldType;
        }

        public async void WorkorderPreviewUIShow(Action? Showed, Action<ICollection<string>>? DisposeEraseTraceCallBack)
        {
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {
                EnjoyTable table = new();
                table.Show();
                table.Activate();
                table.DisposeEraseTraceCallBack = (imeis) => { DisposeEraseTraceCallBack?.Invoke(imeis); };
                Independent(nameof(EnjoyTable), table);
                Showed?.Invoke();
            }, DispatcherPriority.Background);
        }

        public async void ContentPopupToolUIShow(EnjoyContentPopue.InfoPakage Ifpakage)
        {
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {
                EnjoyContentPopue popupTool = new(Ifpakage);
                popupTool.Show();
            }, DispatcherPriority.Background);
        }

        public async void RegexpTestToolUIShow(RegexpTestTool.InfoPakage Ifpakage)
        {
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {
                RegexpTestTool regexpTool = new(Ifpakage);
                regexpTool.Show();
                Independent(nameof(RegexpTestTool), regexpTool);
            }, DispatcherPriority.Background);
        }

        public async void BitwiseXorToolUIShow(string content)
        {
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {
                BitwiseXorUI bitwiseTool = new(content);
                bitwiseTool.Show();
                Independent(nameof(BitwiseXorUI), bitwiseTool);
            }, DispatcherPriority.Background);

        }

        public async void TestStatisticalViewUIShow()
        {
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {
                TestStatisticialTree table = new();
                table.Show();
                Independent(nameof(TestStatisticialTree), table);
            }, DispatcherPriority.Background);
        }

        public async Task ConfigTemplateCreator(JsonSerializerOptions SafetyReferenceJsonOptions)
        {
            if (DatabaseServer.GetCloudDB() is not null and Supabase.Client CloudDB)
            {
                Supabase.Postgrest.Responses.ModeledResponse<ProductConfigField> queryConfigField = await CloudDB.From<ProductConfigField>().Get();

                foreach (var config in queryConfigField.Models)
                {
                    string product = config.FieldProduct;
                    string process = config.FieldProcess;
                    string jsonconfig = config.FieldJson;
                    string path = System.IO.Path.Combine("MyApp".CurrentDir(), "DefaultConfig", $"{product}_{process}.ini");
                    if (DirFileServer.CreateFile(path) is not null and string _path)
                    {
                        ICollection<TestItemDeepSeatedSealed>? _Json = System.Text.Json.JsonSerializer.Deserialize<ICollection<TestItemDeepSeatedSealed>>(jsonconfig, SafetyReferenceJsonOptions);

                        if (_Json is not null)
                        {
                            string ConvertChz = System.Text.Json.JsonSerializer.Serialize(_Json, Function.SafetyReferenceJsonOptions);
                            await DirFileServer.WriteAsync(_path, ConvertChz);
                        }
                    }
                }
            }
        }

        private void WeakAdd(string Name, FrameworkElement Element)
        {
            if (!IndependentMap.TryGetValue(Name, out WeakReference<FrameworkElement>? window))
            {
                IndependentMap.Add(Name, new WeakReference<FrameworkElement>(Element));
            }
            else
            {
                IndependentMap[Name] = new WeakReference<FrameworkElement>(Element);
            }
            Element.Name = Name;
            UIElementDelegate?.Invoke(IndependentMap);
        }

        public void Independent(string name, FrameworkElement? element = null)
        {
            if (element is null)
            {
                IndependentMap.Remove(name);
            }
            else
            {
                WeakAdd(name, element);
            }
        }

        public void SetDelegate(OpenUIElement Delegate)
        {
            UIElementDelegate = Delegate;
        }
    }

    public class MesResportServer
    {
        [Flags]
        public enum BindingType
        {
            QRCODE = 1,
            IMEI = 2,
        }

        public enum ExpectedPrimaryKey
        {
            MesBaseCache
        }

        public readonly ILogger Logger = Serilog.Log.Logger.ForContext<MesResportServer>();

        public ICollection<string> BindingTypes = [nameof(BindingType.QRCODE), nameof(BindingType.QRCODE) + " - " + nameof(BindingType.IMEI), nameof(BindingType.IMEI)];

        public class ElementName
        {
            public static string TestProcessName { get; } = "TestProcessName";

            public static string MesProcessName { get; } = "MesProcessName";

            public static string MesStationName { get; } = "MesStationName";

            public static string MesBingDingType { get; } = "MesBingDingType";
        }

        public sealed class MesargGroups
        {
            public string Barcodes { get; set; } = string.Empty;

            public string WorkOrder { get; set; } = string.Empty;

            public string StationName { get; set; } = string.Empty;

            public string WorkProcedure { get; set; } = string.Empty;

            public string UserAccount { get; set; } = string.Empty;

            public string BindingInfo { get; set; } = string.Empty;

            public string TestInfo { get; set; } = string.Empty;

            public string NGCode { get; set; } = string.Empty;
        }

        public class Response
        {
            public int status { get; set; } = -1;
            public string returninfo { get; set; } = string.Empty;
            public string info { get; set; } = string.Empty;
        }

        public sealed class MesResponse
        {
            public Response? Response { set; get; } = new();

            public string Content { set; get; } = string.Empty;
        }

        readonly IDirFileServer DirFileServer;

        readonly MesargGroups HoldMesargGroups;

        public JsonSerializerOptions SafetyReferenceJsonOptions = new()
        {
            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, //  去除值为Null的属性
            ReferenceHandler = ReferenceHandler.Preserve, //  保护数据，保证引用数据可以正常序列化
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, //  获取一个编码器，保持原编码
            IncludeFields = true, //  包含字段
            WriteIndented = true, //  缩进美化
        };

        public MesResportServer(IDirFileServer _DirFileServer, MesargGroups _MesargGroups)
        {
            DirFileServer = _DirFileServer;
            HoldMesargGroups = _MesargGroups;
            InitConfigMap();
        }

        private async void InitConfigMap()
        {
            bool isReset = true;

            ICollection<ICollection<(string, string, string, IEnumerable<string>)>> MapConfigInfos =
                [
                    [
                        ("未定义", nameof(EnjoyCombobox), ElementName.TestProcessName, []),
                        ("CDz-老化前整机测试", nameof(EnjoyTextBox), ElementName.MesProcessName, []),
                        ("老化前整机测试", nameof(EnjoyTextBox), ElementName.MesStationName, []),
                        (nameof(BindingType.QRCODE), nameof(EnjoyCombobox), ElementName.MesBingDingType, BindingTypes)
                    ]
                    ,
                     [
                        ("未定义", nameof(EnjoyCombobox), ElementName.TestProcessName, []),
                        ("CDz-写号", nameof(EnjoyTextBox), ElementName.MesProcessName, []),
                        ("写号", nameof(EnjoyTextBox),  ElementName.MesStationName, []),
                        (nameof(BindingType.IMEI) + " | " + nameof(BindingType.QRCODE), nameof(EnjoyCombobox), ElementName.MesBingDingType, BindingTypes),
                    ]
                    ,
                     [
                        ("未定义", nameof(EnjoyCombobox), ElementName.TestProcessName, []),
                        ("CDz-老化后整机测试", nameof(EnjoyTextBox), ElementName.MesProcessName, []),
                        ("老化后整机测试", nameof(EnjoyTextBox),  ElementName.MesStationName, []),
                        (nameof(BindingType.IMEI), nameof(EnjoyCombobox), ElementName.MesBingDingType, BindingTypes),
                    ]
                ];

            ICollection<KvpGroup> DefaultMapConfig = [.. MapConfigInfos.Select(x => new KvpGroup
            {
                SHowyDatas = [.. x.Select(x=> new KvpGroup.Sec
                {
                    Content = x.Item1,
                    WidgetType = x.Item2,
                    Flag = x.Item3
                })],
                Cancel = true
            })];

            string? ReadConfig = await DirFileServer.ReadAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.MesMap));

            if (ReadConfig is not null and string _ConfigInfo)
            {
                try
                {
                    ICollection<KvpGroup>? configs = System.Text.Json.JsonSerializer.Deserialize<ICollection<KvpGroup>>(_ConfigInfo, SafetyReferenceJsonOptions);

                    if (configs is not null)
                    {
                        foreach (var config in configs)
                        {
                            foreach (var sec in config.SHowyDatas)
                            {
                                if (sec.Content.IsAbsoluteValidValue() &&
                                    sec.WidgetType.IsAbsoluteValidValue() &&
                                    sec.Flag.IsAbsoluteValidValue())
                                {
                                    isReset = false;
                                }
                            }
                        }
                    }
                }
                catch
                {
                    isReset = true;
                }
            }

            if (isReset)
            {
                string jsonconfig = System.Text.Json.JsonSerializer.Serialize(DefaultMapConfig, SafetyReferenceJsonOptions);
                _ = DirFileServer.WriteAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.MesMap), jsonconfig); 
            }
        }

        public async Task<ICollection<KvpGroup>> RealLocalProcessMap()
        {
            string? LocalMesMap = await DirFileServer.ReadAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.MesMap));

            ICollection<ICollection<(string, string, string)>> TitleHint =
            [
                [
                    ("产测工序", nameof(TextBlock), string.Empty),
                    ("Mes工序", nameof(TextBlock), string.Empty),
                    ("Mes工位", nameof(TextBlock), string.Empty),
                    ("绑定数据", nameof(TextBlock), string.Empty)
                ]
            ];

            ICollection<KvpGroup> LocalMesMapCache =
            [.. TitleHint.Select(x => new KvpGroup
            {
                SHowyDatas = [.. x.Select(x=> new KvpGroup.Sec
                {
                    Content = x.Item1,
                    WidgetType = x.Item2,
                    Flag = x.Item3,
                    Selects = []
                })],
                Cancel = false
            })];

            if (LocalMesMap is not null and string _LocalMesMap)
            {
                try
                {
                    ICollection<KvpGroup>? _MesConfigs = System.Text.Json.JsonSerializer.Deserialize<ICollection<KvpGroup>>(_LocalMesMap, SafetyReferenceJsonOptions);

                    if (_MesConfigs is not null)
                    {
                        LocalMesMapCache.Reteller(_MesConfigs, true);
                    }
                }
                catch
                {
                    InitConfigMap();
                    _ = RealLocalProcessMap();
                    Logger.Print(RuntimeLog.LogType.Error, "mes config format is incomplete, reset now");
                }
            }
            else
            {
                InitConfigMap();
                _ = RealLocalProcessMap();
                Logger.Print(RuntimeLog.LogType.Error, "mes assist config empty, reset now");
            }
            return LocalMesMapCache;
        }

        public static string GetPrimaryKey(ExpectedPrimaryKey key)
        {
            return key switch
            {
                ExpectedPrimaryKey.MesBaseCache => "mes_base",
                _ => "mes_base",
            };
        }

        private static async Task<MesResponse> PushMes(object request, string _apiUrl)
        {
            string responseString = string.Empty;
            try
            {
                using HttpClient _httpClient = new();
                var json = JsonConvert.SerializeObject(request);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                var response = await _httpClient.PostAsync(_apiUrl, content);
                responseString = await response.Content.ReadAsStringAsync();
                return new MesResponse
                {
                    Response = JsonConvert.DeserializeObject<Response>(responseString),
                    Content = responseString
                };
            }
            catch (Exception ex)
            {
                return new MesResponse
                {
                    Response = new Response
                    {
                        status = -1,
                        returninfo = "请求失败",
                        info = ex.Message
                    },
                    Content = responseString
                };
            }
        }

        public async void EchoMesinLoacal(Action<string>? _CallapiUrl = null)
        {
            //  读取缓存数据
            Dictionary<string, Dictionary<string, string>> MesMap = await DirFileServer.ReadIniAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.Mes));

            await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
            {
                //  获取基础缓存数据
                if (MesMap.TryGetValue(GetPrimaryKey(ExpectedPrimaryKey.MesBaseCache), out Dictionary<string, string>? baseMap))
                {
                    static string key(string property)
                    {
                        //  获取标准数据项的中文内容，因为是展示数据，因此检查item2，为true则展示
                        if (ActivityAssistBehivor.Behivor.MesTranslationMap.TryGetValue(property, out (string, bool) translation) &&
                            translation.Item2)
                        {
                            return translation.Item1;
                        }
                        return string.Empty;
                    }
                    //  获取标准接口数据项
                    foreach (var single in HoldMesargGroups.GetPropertys(2))
                    {
                        string _mkey = key(single.Name);

                        //  通过中文key值，获取本地的标准可展示数据value值
                        if (!string.IsNullOrEmpty(_mkey) && baseMap.TryGetValue(_mkey, out string? _mvalue))
                        {
                            single.SetValue(HoldMesargGroups, _mvalue);
                        }
                    }

                    string _key = key("AccessUrl");
                    
                    if (baseMap.TryGetValue(_key, out string? _value))
                    {
                        _CallapiUrl?.Invoke(_value);
                    }
                }
                else
                {
                    _CallapiUrl?.Invoke(string.Empty);
                }
            }, DispatcherPriority.Background);
        }

        public async Task ReadMesAbnormalinLoacal(Action<MesargGroups, string>? CallAbnormal, string _ValidCode)
        {
            //  读取缓存数据
            Dictionary<string, Dictionary<string, string>> MesMap = await DirFileServer.ReadIniAsync(
                               LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.Mes));

            await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
            {
                MesargGroups mesarg = new ();

                //  获取基础缓存数据
                if (MesMap.TryGetValue(_ValidCode, out Dictionary<string, string>? baseMap))
                {
                    //  根据Key值获取中文映射文本
                    static string key(string property)
                    {
                        //  获取标准数据项的中文内容，因为是接口数据，不使用item2过滤（item2过滤时为UI所显示项）
                        if (ActivityAssistBehivor.Behivor.MesTranslationMap.TryGetValue(property, out (string, bool) translation))
                        {
                            return translation.Item1;
                        }
                        return string.Empty;
                    }
                    //  获取标准接口数据项
                    foreach (var single in mesarg.GetPropertys(2))
                    {
                        string _mkey = key(single.Name);

                        //  通过中文key值，获取本地的标准可展示数据value值
                        if (!string.IsNullOrEmpty(_mkey) && baseMap.TryGetValue(_mkey, out string? _mvalue))
                        {
                            single.SetValue(mesarg, _mvalue); //  加载至空对象中
                        }
                    }
                    //  AccessUrl 不在请求对象封装字段中，单独拿出来处理
                    string _key = key("AccessUrl");
                    if (baseMap.TryGetValue(_key, out string? _value))
                    {
                        CallAbnormal?.Invoke(mesarg, _value);
                    }
                    else
                    {
                        CallAbnormal?.Invoke(mesarg, string.Empty);
                    }
                }else CallAbnormal?.Invoke(mesarg, string.Empty);
            }, DispatcherPriority.Background);
        }

        public async Task<Response?> HttpRequest(MesargGroups mesarg, string _apiUrl, bool isWriteErr = true)
        {
            //  isWriteErr 为false 时不编辑原有信息，如报告成功发送，原有信息还是会正常清空，因为已不需要它记录

            MesResportServer.MesResponse Response = await PushMes(mesarg, _apiUrl);

            if (!string.IsNullOrEmpty(mesarg.Barcodes))
            {

                if (Response.Response is not null && Response.Response.status != 0)
                {
                    if (isWriteErr)
                    {
                        await SaveMesinLoacal(mesarg.Barcodes, _apiUrl, false);
                    }
                    return Response.Response;
                }
                else
                {
                    await DirFileServer.WriteIniAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.Mes),
                          mesarg.Barcodes, null);
                    return null;
                }
            }
            return null;
        }

        public async Task SaveMesinLoacal(string PrimaryKey, string MesargPushUrl, bool _saveMain = true)
        {
            Dictionary<string, string> MesMap = [];
            void Add(string _key, string _value)
            {
                if (ActivityAssistBehivor.Behivor.MesTranslationMap.TryGetValue(_key, out (string, bool) translation))
                {
                    if (_saveMain)
                    {
                        if (translation.Item2) MesMap.Add(translation.Item1, _value);
                    }
                    else
                    {
                        MesMap.Add(translation.Item1, _value);
                    }
                }
                else
                {
                    if (!_saveMain) MesMap.Add(_key, _value);
                }
            }

            foreach (var single in HoldMesargGroups.GetPropertys(2))
            {
                string _key = single.Name;
                string _value = string.Empty;

                string? _objectStr = single.GetValue(HoldMesargGroups)?.GetSafetyChar();

                if (string.IsNullOrEmpty(_objectStr))
                {
                    _value = "None";
                }
                else
                {
                    _value = _objectStr;
                }
                Add(_key, _value.GetSafetyChar());
            }

            Add("AccessUrl", MesargPushUrl);

            await DirFileServer.WriteIniAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.Mes), PrimaryKey, MesMap);

            Logger.Print(LogType.Debug, System.Text.Json.JsonSerializer.Serialize(MesMap));
        }
    }

    public class OneNetAccessServer
    {
        public ILogger Logger = Serilog.Log.Logger.ForContext<MesResportServer>();

        public sealed class Response
        {
            public int code { set; get; }
            public object? data { set; get; } = null;
            public string msg { set; get; } = string.Empty;
            public string request_id { set; get; } = string.Empty;
        }

        //  计算当前时间差异，超时期限为一天
        public static long DfrTime()
        {
            DateTime _NowUtc = DateTime.UtcNow;
            DateTime _StdUtc = new (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            long _Dfr = (long)(_NowUtc - _StdUtc).TotalSeconds;
            return _Dfr + 3600;
        }

        private static string Authorization()
        {
            static string UrlEncd(string s)
            {
                return HttpUtility.UrlEncode(s);
            }

            long OneNet_OutLimitTime = DfrTime();
            string OneNet_AccessKey = "j0InL6W81i63K9LfTT13/Q236BTd39xASIwEhnK8jBlvSNeXzrJVn4kFnRSOHr6lXyulDXYfPP7wtC7x/VnSyg==";
            string OneNet_UserID = "101396";
            string OneNet_Version = "2020-05-29";
            string OneNet_Method = "sha1";
            string OneNet_UserID_Var = $"userid/{OneNet_UserID}";
            string OneNet_Signature = new List<string> { OneNet_OutLimitTime.GetSafetyChar(), OneNet_Method, OneNet_UserID_Var, OneNet_Version }.Join("\n");

            byte[] ByteAccessKey = Convert.FromBase64String(OneNet_AccessKey);

            using HMACSHA1 HashTsha1 = new (ByteAccessKey);

            byte[] HashValue = HashTsha1.ComputeHash(Encoding.UTF8.GetBytes(OneNet_Signature));

            string StrHashValue = Convert.ToBase64String(HashValue);

            return new List<string> { $"version={UrlEncd(OneNet_Version)}",
                                    $"res={UrlEncd(OneNet_UserID_Var)}",
                                    $"et={UrlEncd(OneNet_OutLimitTime.GetSafetyChar())}",
                                    $"method={UrlEncd(OneNet_Method)}",
                                    $"sign={UrlEncd(StrHashValue)}",}.Join("&");
        }

        public async Task<Response?> Access(string _apiUrl, string product_id, string imei)
        {
            try
            {
                string _RealUrl = $"{_apiUrl}?product_id={product_id}&device_name={imei}";
                using HttpClient _httpClient = new();
                if (_httpClient.DefaultRequestHeaders.Contains("Authorization"))
                {
                    _httpClient.DefaultRequestHeaders.Remove("Authorization");
                }
                _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", Authorization());
                string response = await _httpClient.GetStringAsync(_RealUrl);

                return System.Text.Json.JsonSerializer.Deserialize<Response>(response);
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, "onenet-Access: ", error.Message);
                return null;
            }
        }
    }

    public sealed class Excel(Dictionary<string, string>? WorkOrderdbMap = null, bool? isCloud = false)
    {
        private readonly ILogger Logger = Log.Logger.ForContext<MesResportServer>();

        private readonly Dictionary<string, string>? DBWorkOrderMap = WorkOrderdbMap;

        private readonly bool IsCloud = isCloud ?? false;

        private readonly ICollection<string> LocalUnfoldSqlDatas = []; //  local datas

        private readonly ICollection<string> LocalPreviewSqlDatas = []; //  local datas

        public static async Task<Dictionary<string, Dictionary<string, ICollection<string>>>?> GetEPPlusExcel(ExcelOptions options, 
                            ExcelOriented orient = ExcelOriented.ColumnOriented)
        {
            Dictionary<string, Dictionary<string, ICollection<string>>>? ExcelResult = [];
            ExcelPackage.License.SetNonCommercialPersonal("My_Private_App");
            await Task.Run(() =>
            {
                try
                {
                    foreach (var file in options.Exc_Files)
                    {
                        using ExcelPackage ExcelEngin = new(new FileInfo(file));
                        ICollection<ExcelWorksheet> WorkSheets = [.. ExcelEngin.Workbook.Worksheets];
                        ICollection<string> SheetNames = [.. WorkSheets.Select(x => x.Name)];
                        if (options.Exc_IsQuerySheet && SheetNames.Count > 1)
                        {
                            CustomMessageBox.InquiryPopupInvoke result = CustomMessageBox.Show(
                                new CustomMessageBox.InquiryListPopupSetting
                                {
                                    Msg_Title = "选择工单文件，可按Shift多选",
                                    Msg_InquiryButtoms = ["取消", "确定"],
                                    Msg_ItemsSource = SheetNames,
                                    Msg_SelectionMode = System.Windows.Controls.SelectionMode.Extended
                                });
                            options.Exc_Sheet = result.selectedValues;
                        }
                        else
                        {
                            if (SheetNames.Count > 0)
                            {
                                options.Exc_Sheet.AddRange(SheetNames);
                            }
                        }
                        for (int sRow = 0; sRow < WorkSheets.Count; sRow++)
                        {
                            ExcelWorksheet sheet = WorkSheets.ElementAt(sRow);
                            ProcessingSheet(sheet, ref ExcelResult, options, orient);
                        }
                    }
                }
                catch
                {
                    ExcelResult = null;
                }
            }).ConfigureAwait(false);

            return ExcelResult;
        }

        // 加工数据，包含横向和纵向加工
        private static void ProcessingSheet(ExcelWorksheet sheet,
                                             ref Dictionary<string, Dictionary<string, ICollection<string>>> result,
                                             ExcelOptions options,
                                             ExcelOriented orient = ExcelOriented.ColumnOriented)
        {
            int ExcelRows = sheet.Dimension.Rows;
            int ExcelColumns = sheet.Dimension.Columns;
            Dictionary<string, ICollection<string>> SheetMap = [];

            if (orient == ExcelOriented.ColumnOriented) //  columns
            {
                for (int column = 1; column <= ExcelColumns; column++)
                {
                    string Title = string.Empty;
                    ICollection<string> ColumnDatas = [];
                    for (int row = 1; row <= ExcelRows; row++)
                    {
                        string Value = sheet.Cells[row, column].Text;
                        if (row == 1)
                        {
                            Title = Value;
                        }
                        else
                        {
                            ColumnDatas.Add(Value);
                        }
                    }

                    string sheet_name = sheet.Name;
                    string column_name = $"第 {column - 1} 列"; //  包含最大值，则减去1才是正常的列值
                    double prograss = Math.Round((double)column / ExcelColumns * 100, 2);
                    prograss = Math.Min(100, prograss);

                    if (options.Exc_VisiblePrograss)
                    {
                        Application.Current.Dispatcher.InvokeAsync(() =>
                        {
                            options.Exc_HintCallBack?.Invoke(sheet_name, column_name, prograss);
                        });
                    }

                    if (!string.IsNullOrEmpty(Title))
                    {
                        SheetMap.TryAdd(Title, ColumnDatas);
                    }

                    if (options.Exc_MaxReaderNum == column)
                    {
                        if (options.Exc_VisiblePrograss)
                        {
                            options.Exc_HintCallBack?.Invoke(sheet_name, column_name, 100.0);
                        }
                        break;
                    }
                }
                result.TryAdd(sheet.Name, SheetMap);
            }
            else //  rows
            {
                for (int row = 1; row <= ExcelRows; row++)
                {
                    string Title = string.Empty;
                    ICollection<string> RowDatas = [];
                    for (int column = 1; column <= ExcelColumns; column++)
                    {
                        string Value = sheet.Cells[row, column].Text;
                        if (row == 1)
                        {
                            Title = "Title";
                            RowDatas.Add(Value);
                        }
                        else
                        {
                            RowDatas.Add(Value);
                        }
                    }

                    string sheet_name = sheet.Name;
                    string row_name = $"第 {row - 1} 行"; //  包含最大值，则减去1才是正常的行值
                    double prograss = Math.Round((double)row / ExcelRows * 100, 2);
                    prograss = Math.Min(100, prograss);
                    if (options.Exc_VisiblePrograss)
                    {
                        System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                        {
                            options.Exc_HintCallBack?.Invoke(sheet_name, row_name, prograss);
                        });
                    }

                    if (string.IsNullOrEmpty(Title))
                    {
                        SheetMap.TryAdd($"{row}", RowDatas);
                    }
                    else
                    {
                        SheetMap.TryAdd(Title, RowDatas);
                    }

                    if (options.Exc_MaxReaderNum == row)
                    {
                        if (options.Exc_VisiblePrograss)
                        {
                            options.Exc_HintCallBack?.Invoke(sheet_name, row_name, 100.0);
                        }
                        break;
                    }
                }
                result.TryAdd(sheet.Name, SheetMap);
            }
        }

        // 共包含三种读取文档的库， 普通读取方法，1.流读取，然后手动整理数据 2.XSSF 读取，支持xlsx 3.HSSF 读取
        public async Task<Dictionary<string, Dictionary<string, ICollection<string>>>> GetRBTExcel(ExcelOptions options)
        {
            Dictionary<string, Dictionary<string, ICollection<string>>> ToTalExcelDict = [];

            await Task.Run(async () =>
            {
                bool CanCel = false;

                foreach (var file in options.Exc_Files)
                {
                    string? Suffix = System.IO.Path.GetExtension(file).ToUpper();

                    if (Suffix is not null)
                    {
                        if (Suffix == ".CSV")
                        {
                            using FileStream FileStream = new(file, FileMode.Open, FileAccess.Read);
                            using StreamReader FileReader = new(FileStream, Encoding.GetEncoding("GB2312"));

                            string? LineContent;

                            int index = 0;

                            string sheet_name = System.IO.Path.GetFileName(file);

                            Dictionary<string, ICollection<string>> ExcelSecDict = [];

                            if (options.Exc_VisiblePrograss)
                            {
                                _ = System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                                {
                                    options.Exc_HintCallBack?.Invoke(sheet_name, "______", 0);
                                });
                            }

                            while ((LineContent = await FileReader.ReadLineAsync()) != null)
                            {
                                IEnumerable<string> Row = RegExp.RegExpMultiSpacing().Split(LineContent).Where(x => !string.IsNullOrEmpty(x.Trim()));

                                string row_name = $"第 {index} 行"; //  包含最大值，则减去1才是正常的行值

                                if (options.Exc_VisiblePrograss)
                                {
                                    _ = System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                                    {
                                        options.Exc_HintCallBack?.Invoke(sheet_name, row_name, 50);
                                    });
                                }

                                if (index == 0)
                                {
                                    ExcelSecDict.Add("Title", [.. Row]);
                                }
                                else
                                {
                                    ExcelSecDict.Add($"{index}", [.. Row]);
                                }

                                if (options.Exc_VisiblePrograss)
                                {
                                    if (options.Exc_MaxReaderNum == index)
                                    {
                                        if (options.Exc_VisiblePrograss)
                                        {
                                            options.Exc_HintCallBack?.Invoke(sheet_name, "______", 100.0);
                                        }
                                        break;
                                    }
                                }
                                index++;
                            }
                            if (options.Exc_VisiblePrograss)
                            {
                                _ = System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                                {
                                    options.Exc_HintCallBack?.Invoke(sheet_name, "______", 100);
                                });
                            }

                            ToTalExcelDict.Add(sheet_name, ExcelSecDict.DeepCopy() ?? []);
                        }
                        else if (Suffix == ".XLSX")
                        {
                            try
                            {
                                int index = 0;

                                int tt_index = 0;

                                string sheet_name = string.Empty;

                                Dictionary<string, ICollection<string>> ExcelSecDict = [];

                                XSSFExcelExtractor excelExtractor = new(OPCPackage.Open(file))
                                {
                                    IncludeSheetNames = true //  optional
                                };

                                string[] SectionContent = RegExp.RegExpWrapWork().Split(excelExtractor.Text);

                                foreach (var sec in SectionContent)
                                {
                                    string[] Row = RegExp.RegExpEmpty().Split(sec);

                                    if (Row.Length == 1 || !Row.Where(x => !string.IsNullOrEmpty(x)).Any())
                                    {
                                        if (ExcelSecDict.Count > 0)
                                        {
                                            ToTalExcelDict.Add(sheet_name, ExcelSecDict.DeepCopy() ?? []);
                                            tt_index = index;
                                            ExcelSecDict.Clear();
                                        }
                                        sheet_name = Row.ElementAt(0);
                                    }
                                    else if (index - tt_index == 1)
                                    {
                                        ExcelSecDict.Add("Title", [.. Row]);
                                    }
                                    else
                                    {
                                        ExcelSecDict.Add($"{index}", [.. Row]);
                                    }
                                    index++;

                                    double prograss = Math.Round((double)index / SectionContent.Length * 100, 2);
                                    prograss = Math.Min(100, prograss);

                                    if (options.Exc_VisiblePrograss)
                                    {
                                        _ = System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                                        {
                                            options.Exc_HintCallBack?.Invoke(sheet_name, $"第 {index} 行", prograss);
                                        });
                                    }

                                    if (options.Exc_MaxReaderNum == index)
                                    {
                                        if (options.Exc_VisiblePrograss)
                                        {
                                            options.Exc_HintCallBack?.Invoke(sheet_name, $"第 {index} 行", 100.0);
                                        }
                                        break;
                                    }
                                }
                                excelExtractor.Close();
                            }
                            catch (Exception error)
                            {
                                Logger.Print(RuntimeLog.LogType.Error, $"XLSX Error: {error.Message}");
                            }
                        }
                        else if (Suffix == ".XLS")
                        {
                            using FileInputStream FileStream = new(new FileStream(file, FileMode.Open, FileAccess.Read));
                            POIFSFileSystem Fsystem = new(FileStream);
                            using HSSFWorkbook workbook = new(Fsystem);
                            
                            Dictionary<string, ICollection<string>> ExcelSecDict = [];

                            for (int sheet_index = 0; sheet_index < workbook.NumberOfSheets; sheet_index++)
                            {
                                HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(sheet_index);
                                string sheet_name = sheet.SheetName;

                                for (int row_index = sheet.FirstRowNum; row_index <= sheet.LastRowNum; row_index++)
                                {
                                    string key = $"{row_index}";

                                    IRow Row = sheet.GetRow(row_index);

                                    if (Row != null)
                                    {
                                        for (int cell_index = Row.FirstCellNum; cell_index <= Row.LastCellNum; cell_index++)
                                        {
                                            NPOI.SS.UserModel.ICell cell = Row.GetCell(cell_index);

                                            if (cell == null) continue;

                                            if (row_index == 0)
                                            {
                                                if (ExcelSecDict.TryGetValue("Title", out ICollection<string>? values))
                                                {
                                                    values.Add(cell.StringCellValue);
                                                }
                                                else
                                                {
                                                    ExcelSecDict.Add("Title", [cell.StringCellValue]);
                                                }
                                            }
                                            else
                                            {
                                                if (ExcelSecDict.TryGetValue(key, out ICollection<string>? values))
                                                {
                                                    values.Add(cell.StringCellValue);
                                                }
                                                else
                                                {
                                                    ExcelSecDict.Add(key, [cell.StringCellValue]);
                                                }
                                            }
                                        }
                                    }
                                    double prograss = Math.Round((double)row_index / sheet.LastRowNum * 100, 2);
                                    prograss = Math.Min(100, prograss);

                                    if (options.Exc_VisiblePrograss)
                                    {
                                        _ = System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                                        {
                                            options.Exc_HintCallBack?.Invoke(sheet_name, $"第 {row_index} 行", prograss);
                                        });
                                    }

                                    if (options.Exc_MaxReaderNum == row_index)
                                    {
                                        if (options.Exc_VisiblePrograss)
                                        {
                                            options.Exc_HintCallBack?.Invoke(sheet_name, $"第 {row_index} 行", 100.0);
                                        }

                                        CanCel = true;
                                        break;
                                    }
                                }
                                ToTalExcelDict.Add(sheet_name, ExcelSecDict.DeepCopy() ?? []);
                                ExcelSecDict.Clear();
                                if (CanCel) break;
                            }
                            Fsystem.Close();
                        }
                    }
                    if (CanCel) break;
                }
            });
            return ToTalExcelDict;
        }

        private async Task<bool> IPPrepare()
        {
            if (DBWorkOrderMap != null && !DBWorkOrderMap.Keys.Select(x => !string.IsNullOrEmpty(x)).Any())
            {
                await CustomMessageBox.Show(new CustomMessageBox.InquiryNmPopupSetting { 
                    Msg_Title = "提示", 
                    Msg_InquiryIcon = 1, 
                    Msg_BodyText = "不存在映射数据，请选择数据库-字段映射，添加映射数据", 
                    Msg_InquiryButtoms = ["知道了"] });
                return true;
            }
            return false;
        }

        // 提取依赖项的后缀
        private async Task IPDependencyAppend<T>(ICollection<T> values, ICollection<string> dependencys, Dictionary<string, ICollection<string>> difference)
        {
            try
            {
                await Task.Run(() =>
                {
                    int index = 0;
                    foreach (var property in values)
                    {
                        foreach (var depedency in dependencys)
                        {
                            (string?, string?, ICollection<string?>)? differences = difference[depedency].GetDifference<string>();
                            DependencyDBPropertyType DependencyType = ActivityAssistBehivor.Behivor.DBDependencyMap[depedency].Value;
                            if (property is not null && differences is not null &&
                                property.GetProperty(depedency) is not null and PropertyInfo depedencyInfo)
                            {
                                switch (DependencyType)
                                {
                                    case DependencyDBPropertyType.Difference:
                                        depedencyInfo.SetValue(property, differences.Value.Item3.ElementAt(index));
                                        break;
                                    case DependencyDBPropertyType.PointStart:
                                        depedencyInfo.SetValue(property, differences.Value.Item1);
                                        break;
                                    case DependencyDBPropertyType.PointEnd:
                                        depedencyInfo.SetValue(property, differences.Value.Item2);
                                        break;
                                }
                            }
                        }
                        index++;
                    }
                });
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"IPDependencyAppend Error: {error.Message}");
            }
        }

        private async Task<(ICollection<string>, Dictionary<string, ICollection<string>>)> IPGetDifference(ICollection<WorkOrderUnfold> unfolds) //  获取差异字典所需数据
        {
            ICollection<string> dependencys = [.. ActivityAssistBehivor.Behivor.DBDependencyMap.Keys];

            Dictionary<string, ICollection<string>> difference = [];

            try
            {
                await Task.Run(() =>
                {
                    if (ActivityAssistBehivor.Behivor.DBDependencyMap.Keys.Count > 0)
                    {
                        foreach (var unfold in unfolds)
                        {
                            foreach (var depedency in dependencys)
                            {
                                string previorKey = ActivityAssistBehivor.Behivor.DBDependencyMap[depedency].Key;

                                if (unfold.GetProperty(previorKey) is not null and PropertyInfo property &&
                                    property.GetValue(unfold) is not null and object value)
                                {
                                    if (difference.TryGetValue(depedency, out ICollection<string>? values))
                                    {
                                        values.Add(value.GetSafetyChar());
                                    }
                                    else
                                    {
                                        difference.Add(depedency, [value.GetSafetyChar()]);
                                    }
                                }
                            }
                        }
                    }
                });
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
            return (dependencys, difference);
        }

        // 提取为字符串sql语句，供本地数据库导入
        private async Task IPCombinationSql<T>(IEnumerable<T> values)
        {
            try
            {
                await Task.Run(() =>
                {
                    foreach (var value in values)
                    {
                        ICollection<string> propertyNames = [];

                        ICollection<string> propertyValues = [];

                        if (value is not null)
                        {
                            foreach (PropertyInfo property in value.GetPropertys())
                            {
                                ColumnAttribute? attribute = property.GetCustomAttribute<ColumnAttribute>();
                                if (attribute is not null)
                                {
                                    string? _key = attribute.ColumnName;
                                    string? _value = property.GetValue(value)?.GetSafetyChar();

                                    if (!string.IsNullOrEmpty(_value) && !string.IsNullOrEmpty(_key))
                                    {
                                        propertyNames.Add(_key);
                                        propertyValues.Add(_value);
                                    }
                                }
                            }

                            string propertyType = typeof(T).Name;

                            switch (propertyType)
                            {
                                case nameof(WorkOrderUnfold):
                                    LocalUnfoldSqlDatas.Add($"INSERT INTO workorder_unfold({propertyNames.Join(",")}) " +
                                                            $"VALUES({propertyValues.Join(",", true)})");

                                    break;
                                case nameof(WorkOrderPreview):
                                    LocalPreviewSqlDatas.Add($"INSERT INTO workorder_preview({propertyNames.Join(",")}) " +
                                                             $"VALUES({propertyValues.Join(",", true)})");

                                    break;
                            }
                        }
                    }
                });
            }
            catch (Exception error)
            {
                Logger.Print(RuntimeLog.LogType.Error, $"{MethodBase.GetCurrentMethod()?.Name} Error: {error.Message}");
            }
        }

        // 根据读取的文档内容，填充数据模型
        private async Task IPLoaderSheetValue(Dictionary<string, ICollection<string>> sheetValue, Action<WorkOrderUnfold, WorkOrderPreview> CallBack)
        {
            await Task.Run(() =>
            {
                ICollection<string> DBMapTitle = [];

                ICollection<string> SecTitle = [];

                foreach (var section in sheetValue)
                {
                    if (section.Key == "Title")
                    {
                        SecTitle = section.Value; //  first row data , map translation
                        DBMapTitle = DBWorkOrderMap?.Values ?? SecTitle;
                    }
                    else
                    {
                        int column_index = 0;

                        ICollection<string> row_values = section.Value;

                        WorkOrderUnfold orderUnfold = new();

                        WorkOrderPreview orderPreview = new();

                        ICollection<PropertyInfo> UnfoldPropertys = orderUnfold.GetPropertys(2);

                        ICollection<PropertyInfo> PreviewPropertys = orderPreview.GetPropertys(2);

                        while (column_index != row_values.Count) // 遍历所有列
                        {
                            if (DBMapTitle.Count > column_index)
                            {
                                string column_name = DBMapTitle.ElementAt(column_index); // 映射的列名

                                int index = SecTitle.IndexOf(column_name); // 实际文档的列名，获取它的索引，将根据这个索引来获取它的对应的值

                                if (index != -1)
                                {
                                    string value = row_values.ElementAt(index); // 根据实际的文档列名索引取值

                                    ICollection<string>? realKeys = DBWorkOrderMap?.GetSafetyKey<string, string>(column_name); //  对应的数据库映射字段

                                    if (realKeys is not null && realKeys.Count >= 1) // 可能会有多个数据库列名
                                    {
                                        foreach (var realKey in realKeys) // 根据数据库列名，获取模型的属性，然后赋值
                                        {
                                            var findUnfoldPropertys = UnfoldPropertys.Where(x => x.Name == realKey);

                                            if (findUnfoldPropertys.Any())
                                            {
                                                foreach (var property in findUnfoldPropertys)
                                                {
                                                    if (property.CanSafetyConvert(value, out object? _value1))
                                                    {
                                                        property.SetValue(orderUnfold, _value1);
                                                    }
                                                }
                                            }

                                            var findPreviewProperty = PreviewPropertys.Where(x => x.Name == realKey);

                                            foreach (var property in findPreviewProperty) // 根据数据库列名，获取模型的属性，然后赋值
                                            {
                                                if (property.CanSafetyConvert(value, out object? _value1))
                                                {
                                                    property.SetValue(orderPreview, _value1);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            column_index++;
                        }
                        CallBack.Invoke(orderUnfold, orderPreview);
                    }
                }
            });
        }

        public async Task<Dictionary<string, Dictionary<string, ICollection<string>>>> AutoRead(ExcelOptions options)
        {
            Dictionary<string, Dictionary<string, ICollection<string>>>? ResultExcelDict = [];

            try
            {
                ResultExcelDict = await GetEPPlusExcel(options, ExcelOriented.RowOriented);

                if (ResultExcelDict is null)
                {
                    Logger.Print(RuntimeLog.LogType.Warning, $"the UPPlus is not support file extend " +
                        $"'{options.Exc_Files.Select(x => $"{System.IO.Path.GetFileName(x)} - {System.IO.Path.GetExtension(x)}").Join(" - ")} ', " +
                        $"try RBT read now");
                    ResultExcelDict = await GetRBTExcel(options);
                }
            }
            catch
            {
                Logger.Print(RuntimeLog.LogType.Warning, $"the UPPlus is not support file extend " +
                        $"'{options.Exc_Files.Select(x => $"{System.IO.Path.GetFileName(x)} - {System.IO.Path.GetExtension(x)}").Join(" - ")} ', " +
                        $"try RBT read now");
                ResultExcelDict = await GetRBTExcel(options);
            }

            return ResultExcelDict;
        }

        /// <summary>
        /// <para> *** 当前方法为专为数据库数据导入设计，只获取内容则使用 GetEPPlusExcel 和 GetRBTExcel 方法进行读取 *** </para>
        /// <para> files 需读取的文件 </para>
        /// <para> WorkOrdersCheck 读取之后确认的文件工单回调，即检查工单是否在数据库中,返回结果为布尔值 </para>
        /// <para> Process 读取进度回调，进度内容为 进度值 、进度提示 </para>
        /// <para> DisposeResult 读取结果回调，内容为 布尔值、对象、对象，即是否为云数据库、unfold 模型集合或字符串sql集合、preview 模型集合或字符串sql集合 </para>
        /// <para> UnexpectedCase 异常情况下的回调，即工单因为工序选择原因，导致映射不匹配工单号为空，或文件本身就存在乱码导致为空的，触发该回调 </para>
        /// </summary>
        /// <param name="files"></param>
        /// <param name="WorkOrdersCheck"></param>
        /// <param name="Process"></param>
        /// <param name="DisposeResult"></param>
        /// <param name="UnexpectedCase"></param>
        public async void ReadExcelAsync(IEnumerable<string> files,
                                         Func<IEnumerable<string>, Task<bool>> WorkOrdersCheck, 
                                         Action<double, string> Progress, 
                                         Action<bool, object, object> DisposeResult,
                                         Action? UnexpectedCase = null)
        {
            try
            {
                bool Prepare = await IPPrepare();

                await Task.Run(async () =>
                {
                    ICollection<WorkOrderUnfold> CloudSqlUnfoldDatas = []; //  cloud datas

                    ICollection<WorkOrderPreview> CloudSqlPreviewDatas = []; //  cloud datas

                    Dictionary<string, Dictionary<string, ICollection<string>>>? ToTalExcelDict = await AutoRead(new ExcelOptions(files)
                    {
                        Exc_IsQuerySheet = true,
                        Exc_HintCallBack = (sheet, hint, process) =>
                        {
                            Progress.Invoke(process, $"工作簿: {sheet} {hint} 读取中...");
                        }
                    });

                    if (ToTalExcelDict is not null)
                    {
                        foreach (var sheet in ToTalExcelDict) //  looping all sheet
                        {
                            Dictionary<string, ICollection<string>> sheet_value = sheet.Value; //  all row datas

                            await IPLoaderSheetValue(sheet_value, (unfold, preview) =>
                            {
                                //  添加单行数据，限制统计表导入条件
                                CloudSqlUnfoldDatas.Add(unfold);
                                if (!CloudSqlPreviewDatas.Any(x => x.WorkorderNum == preview.WorkorderNum))
                                {
                                    CloudSqlPreviewDatas.Add(preview);
                                }
                            });
                            try
                            {

                                var Difference = await IPGetDifference(CloudSqlUnfoldDatas);
                                var dependencys = Difference.Item1;
                                var difference = Difference.Item2;

                                await IPDependencyAppend<WorkOrderUnfold>(CloudSqlUnfoldDatas, dependencys, difference);

                                await IPDependencyAppend<WorkOrderPreview>(CloudSqlPreviewDatas, dependencys, difference);

                                if (!IsCloud)
                                {
                                    await IPCombinationSql<WorkOrderUnfold>(CloudSqlUnfoldDatas);
                                    await IPCombinationSql<WorkOrderPreview>(CloudSqlPreviewDatas);
                                }
                            }
                            catch (Exception error)
                            {
                                await CustomMessageBox.Show(new CustomMessageBox.InquiryNmPopupSetting { 
                                    Msg_Title = "警告", 
                                    Msg_InquiryIcon = 1, 
                                    Msg_BodyText = error.Message, 
                                    Msg_InquiryButtoms = ["知道了"] });
                            }
                        }

                        IEnumerable<string> WorkOrders = CloudSqlPreviewDatas.Select(x => x.WorkorderNum).Distinct();

                        await WorkOrdersCheck.Invoke(WorkOrders);

                        if (WorkOrders.Where(x=>!string.IsNullOrEmpty(x)).Any())
                        {
                            if (IsCloud)
                            {
                                DisposeResult.Invoke(IsCloud, CloudSqlUnfoldDatas, CloudSqlPreviewDatas);
                            }
                            else
                            {
                                LocalUnfoldSqlDatas.Clear();
                                LocalPreviewSqlDatas.Clear();

                                await IPCombinationSql<WorkOrderUnfold>(CloudSqlUnfoldDatas);

                                await IPCombinationSql<WorkOrderPreview>(CloudSqlPreviewDatas);

                                DisposeResult.Invoke(IsCloud, LocalUnfoldSqlDatas, LocalPreviewSqlDatas);
                            }
                        }
                        
                        else
                        {
                            UnexpectedCase?.Invoke();
                        }
                    }
                });
            }
            catch (Exception error)
            {
                Logger.Print(LogType.Error, $"ReadExcelAsync Error: {error.Message}");
            }
        }
    }

    public sealed class Product(IDataBaseServer DataBaseServer,
                                IDirFileServer DirFileServer,
                                IDenCryptoGraphicServer cryptServer)
    {
        private readonly ILogger Logger = Log.Logger.ForContext<Product>();

        private readonly IDataBaseServer DBServer = DataBaseServer;

        private readonly IDirFileServer IOServer = DirFileServer;

        private readonly IDenCryptoGraphicServer CryptServer = cryptServer;

        private readonly ICollection<string> EchoSelectValue = [];

        private readonly ICollection<string> ProductSelectNames = [];

        private readonly Dictionary<string, ICollection<string>> PairClassify = [];

        public async void LoadProduct(Action? Start = null,
                                      Action<string, string>? ProductInfoCallBack = null,
                                      Action<KeyValuePairSealed>? SelectItemCallBack = null,
                                      Action? DBLoadFailCallBack = null,
                                      Action<string>? ApplyProductCallBack = null,
                                      Action<ICollection<string>>? SelectEchoItemsCallBack = null,
                                      Action<Dictionary<string, ICollection<string>>>? ClassifyCallBack = null)
        {
            Start?.Invoke();

            DB.DB_TYPE _DBTYPE = await DBServer.CheckDBSurvival(DB.G_MapKeyName(DB.DB_MAPKEY.LocalDataCache));

            if (_DBTYPE == DB.DB_TYPE.DB_Local)
            {
                await LoadLocalDB(DBLoadFailCallBack, ProductInfoCallBack, SelectItemCallBack, ApplyProductCallBack);
            }
            else if (_DBTYPE == DB.DB_TYPE.DB_Cloud)
            {
                await LoadColudDB(DBLoadFailCallBack, ProductInfoCallBack, SelectItemCallBack, ApplyProductCallBack);
            }

            if (EchoSelectValue.Count > 0)
            {
                //  获取预期的产品名称，这里剔除了固定项，保留有效的产品名
                IEnumerable<string> ValidProductName = ProductSelectNames.Where(x => !ActivityAssistBehivor.Behivor.ProductFixedOpptions.Keys.Select(x => x.Name).Contains(x));

                //  如果当前应用的产品不在当前产品集合中时，获取集合中的第一个产品作为默认项，避免其他产品的数据遗留
                if (!ValidProductName.Contains(EchoSelectValue.ElementAt(0)) &&
                     ValidProductName.Any())
                {
                    string _tempProduct = ValidProductName.ElementAt(0);

                    if (PairClassify.TryGetValue(_tempProduct, out ICollection<string>? _processs) &&
                        _processs is not null)
                    {
                        EchoSelectValue.Clear();
                        EchoSelectValue.Add(_tempProduct);
                        EchoSelectValue.Add(_processs.ElementAt(0));
                    }
                }
            }

            SelectEchoItemsCallBack?.Invoke(EchoSelectValue);

            ClassifyCallBack?.Invoke(PairClassify);

            await Task.Delay(2000);

            EchoSelectValue.Clear();

            ProductSelectNames.Clear();

            PairClassify.Clear();

            Logger.Print(LogType.Debug, EchoSelectValue.Count, PairClassify.Count, ProductSelectNames.Count);
        }

        private async Task<Dictionary<string, Dictionary<string, string>>> ReadLocalConfig()
        {
            var readLocal = await IOServer.ReadIniAsync(LocalConfig.Path.Object.G_Path(LocalConfig.Path.FileType.Nor))
                            .ConfigureAwait(false);

            return readLocal;
        }

        //  添加工序数据
        private async Task LoaderData(string product, string process, int treekey, int apply, 
                                      Action<KeyValuePairSealed>? SelectItemCallBack = null,
                                      Action<string>? ApplyProductCallBack = null)
        {
            if (treekey == 0) //  产品名称项直接添加
            {
                var readLocal = await ReadLocalConfig();

                if (readLocal.TryGetValue(LocalConfig.OwnerKey.BS, out Dictionary<string, string>? _Value) &&
                    _Value.TryGetValue($"{LocalConfig.BSCacheTreeKey.ExpectProduct}", out string? _ExpectProduct))
                {
                    foreach (var exp in _ExpectProduct.Split(','))
                    {
                        if (product == CryptServer.DEbase64(exp))
                        {
                            SelectItemCallBack?.Invoke(new KeyValuePairSealed("\ue691", product));
                        }
                    }
                }
                else
                {
                    SelectItemCallBack?.Invoke(new KeyValuePairSealed("\ue691", product));
                }

                ProductSelectNames.Add(process);
            }
            else //  带有子项的则做好分类，即所属产品 - 包含工序
            {
                if (PairClassify.TryGetValue(product, out ICollection<string>? values))
                {
                    values.Add(process);
                }
                else
                {
                    PairClassify[product] = [process];
                }
            }

            if (apply == 1 && treekey == 1) //  获取包含子项的已应用数据
            {
                ApplyProductCallBack?.Invoke(product);
                EchoSelectValue.Add(product);
                if (!string.IsNullOrEmpty(process)) EchoSelectValue.Add(process);
            }
        }

        // 经过LoaderData加载EchoSelectValue之后，如果EchoSelectValue还是空的，应考虑一个默认项
        private void GetConfigInfo(ICollection<object> products, ICollection<object> processs, Action<string, string>? ProductInfoCallBack = null)
        {
            //  没有应用项或者不存在子项时，默认显示第一条数据
            if (EchoSelectValue.Count == 0 && products.Count > 0 && products.Count > 0)
            {
                EchoSelectValue.Add(products.ElementAt(0).GetSafetyChar());
                if (!string.IsNullOrEmpty(processs.ElementAt(0).GetSafetyChar())) EchoSelectValue.Add(processs.ElementAt(0).GetSafetyChar());
            }

            if (EchoSelectValue.Count == 2)
            {
                ProductInfoCallBack?.Invoke(EchoSelectValue.First(), EchoSelectValue.ElementAt(1));
            }
        }

        private async Task LoadColudDB(Action? DBLoadFail = null,
                                       Action<string, string>? ProductInfoCallBack = null,
                                       Action<KeyValuePairSealed>? SelectItemCallBack = null,
                                       Action<string>? ApplyProductCallBack = null)
        {
            if (DBServer.GetCloudDB() is not null and Supabase.Client CloudDB)
            {
                var queryResult = await CloudDB.From<ProductConfigRelation>().Get();

                if (queryResult.Models.Count > 0)
                {
                    List<object> products = [];
                    List<object> processs = [];

                    foreach (var model in queryResult.Models)
                    {
                        await LoaderData(model.PrdName, model.PrdProcess, model.PrdTreeKey, model.PrdApply, SelectItemCallBack, ApplyProductCallBack);

                        products.Add(model.PrdName); processs.Add(model.PrdProcess);
                    }
                    GetConfigInfo(products, processs, ProductInfoCallBack);
                }
                else
                {
                    DBLoadFail?.Invoke();
                }
                Logger.Print(RuntimeLog.LogType.Debug, "cloud product extract completed");
            }
        }

        private async Task LoadLocalDB(Action? DBLoadFail = null,
                                       Action<string, string>? ProductInfoCallBack = null,
                                       Action<KeyValuePairSealed>? SelectItemCallBack = null,
                                       Action<string>? ApplyProductCallBack = null)
        {
            string queryProductSql = $"SELECT * FROM product_config_relation";

            if (await DBServer.LocalDBQueryFree(queryProductSql) is var queryResult &&
                queryResult != null)
            {
                if (queryResult.ErrorHint == null &&
                    queryResult.Result.TryGetValue(queryProductSql, out Dictionary<string, ICollection<object>>? dataDict) &&
                    dataDict.TryGetValue("prd_id", out ICollection<object>? Ids) &&
                    dataDict.TryGetValue("prd_name", out ICollection<object>? Products) &&
                    dataDict.TryGetValue("prd_process", out ICollection<object>? Processs) &&
                    dataDict.TryGetValue("prd_treekey", out ICollection<object>? Childkeys) &&
                    dataDict.TryGetValue("prd_apply", out ICollection<object>? Applys) &&
                    Products != null && Processs != null)
                {
                    if (Products.Count > 0)
                    {
                        for (int index = 0; index < Products.Count; index++)
                        {
                            string id = Ids.ElementAt(index).GetSafetyChar();
                            string product = Products.ElementAt(index).GetSafetyChar();
                            string process = Processs.ElementAt(index).GetSafetyChar();
                            int treekey = int.Parse(Childkeys.ElementAt(index).GetSafetyChar());
                            int apply = int.Parse(Applys.ElementAt(index).GetSafetyChar());

                            await LoaderData(product, process, treekey, apply, SelectItemCallBack, ApplyProductCallBack);
                        }
                    }
                    else
                    {
                        DBLoadFail?.Invoke();
                    }
                    GetConfigInfo(Products, Processs, ProductInfoCallBack);
                }
            }

            Logger.Print(RuntimeLog.LogType.Debug, "local product extract completed");
        }
    }
}